1 Descripción de la base de datos

El conjunto de datos contiene ubicaciones de estaciones meteorologicas ubicadas en el pais de Mexico, algunos detalles sobre las estaciones meteorologicas son los siguentes:

el conjunto de datos contiene 493 archivos de excel, donde estos se dividen en estaciones para los estados correspondientes que son Chiapas (5), Tabasco (1) y Veracruz (6) con 5, 1 y 6 estaciones meteorologicas en cada estado correspondientemente, entonces los 493 archivos van variando conforme al tiempo, algunos conforme a años, otros conforme a meses, otros conforme a conjunto de meses en las 12 estaciones meteorologicas muestreadas, pero todos varian conforme a dias respectivamente. A continuación se muestran los nombres de las estaciones que contienen los estados correspondientes:

Veracruz (6 estaciones)

Chiapas (5 estaciones)

Tabasco (1 estación)

Asi tambien existen muchos archivos de excel vacios, entre ellos se encuentran.

1.1 descripción de variables

las variables que se incluyen en los conjuntos de datos son los siguientes:

  • SR = Radiación solar

  • Rain = Lluvia (tomada en el tiempo en horas)

  • DP = Temperatura al punto de rocío.

  • RH = Humedad relativa

  • TS = Temperatura a 10 cm de la superficie

  • ATC = Air traffic control (trafico de control aereo)

  • WS = velocidad del viento

  • WD = Dirección del viento

  • QFF = QFF es un código aeronáutico. Es la presión MSL(Mean Sea Level, altitud tomando como referencia el nivel medio del mar) derivada de las condiciones de la estación meteorológica local. De acuerdo con la práctica meteorológica QFF es la presión media al nivel del mar, derivada teniendo en cuenta las condiciones de temperatura reales.

  • BP = La presión atmosférica, también conocida como presión barométrica (después del barómetro), es la presión dentro de la atmósfera de la Tierra.

1.2 Descripción de las estaciones meteorologicas

Descripción de una Estación Sinóptica Meteorológica - ESIME

Una Estación Sinóptica Meteorológica es un conjunto de dispositivos eléctricos que realizan mediciones de las variables meteorológicas de manera automática. Generan una base de datos y generan un mensaje sinóptico cada tres horas.

Los mensajes sinópticos son reportes que se generan simultáneamente en todos los observatorios cada tres horas y presentan información meteorológica de tiempo presente y pasado de manera codificada. Los mensajes sinópticos se rigen por el Tiempo Universal Coordinado (UTC).

Nota: El área representativa de las estaciones es de 5 km de radio aproximadamente, en terreno plano, excepto en terreno montañoso. (Referencia OMM número 100 y 168)

knitr::include_graphics("f0.jpg", dpi = 10)
Estación ESIME

Estación ESIME

1.3 descripción del estudio

Muy bien, principalmente estamos interesados en medir en primer lugar la lluvia (rain) mediante valores extremos y el uso de geoestadistica, pero para ello debemos considerar la lluvia o mejor conocida como precipitaciones extremas.

Conforme a Robert Monjo, Wikipedia y diversos autoeres, podemos categorizar la precipitación conforme a estudios de la Agencia Estatal de Meteorología, los cuales indican que

Si queremos estudiar el comportamiento de la lluvia en el tiempo, debemos fijarnos en cómo se distribuye la intensidad a lo largo del mismo. Usualmente se usa el concepto de intensidad para referirnos a valores medio, es decir, a una cierta cantidad de precipitación registrada en un tiempo determinado: una hora, un minuto, o bien el paso entre dos oscilaciones de tiempo de una estación automática.

Tabla 1. Clasificación de la lluvia según la intensidad media en una hora. Agencia Estatal de Meteorología.

knitr::include_graphics("f1.png", dpi = 10)

Muy bien, entonces para nuestro conjunto de datos tenemos las mediciones que van desde 10 min, 1 hora, 3 horas, 6 horas y 24 horas, entonces para tomar en cuenta la información anterior nos vamos a centrar en las mediciones que se realizaron por hora.

A continuación como ejemplo vamos a seleccionar el conjunto de datos de Chiapas (esto debido a que tiene 5 estaciones pero tambien pudimos seleccionar Veracruz) y conforme a la metodologia de A. C. Davison, S. A. Padoan and M. Ribatet, considerare la precipitación maxima diaria de los meses de junio a octubre para los años 2018, 2019 y 2020, en 5 estaciones meteorológicas en la región de Chiapas, proporcionada por el servicio meteorológico nacional. La elección de estos meses es dedibo a que este conjunto de meses se encuentran dentro del verano, algo que es importante destacar es el comentario de Gery-co Prankster, (2010), el cual indica que las precipitaciones son mayores es esa temporada, sin embargo el Verano: inicia el 21 de junio y finaliza el 22 de septiembre. Por lo tanto para el analisis se consideran los meses de junio a octubre.

Como bien sabemos, Chiapas tiene 5 estaciones, en donde en nuestro conjunto de datos se encuentra la siguiente información.

  • Arriaga :

    • 2006: ene-dic
    • 2007: ene-jun
    • 2009: may-dic
    • 2010: mar
    • 2011: sep-dic
    • 2012: ene-nov
    • 2014: feb-may
    • 2018: ene-jun
    • 2019: ene-dic
    • 2020: ene-dic
  • Comitan

    • 2013: ene-dic
    • 2014: ene-dic
    • 2015: ene-dic
    • 2016: ene-dic
    • 2017: ene-dic
    • 2018: ene-jun, jul-dic
    • 2019: ene-dic
    • 2020: ene-dic
  • San Cristobal de las Casas

    • 2013: ene-dic
    • 2014: ene-dic
    • 2015: ene-dic
    • 2016: ene-dic
    • 2017: ene-dic
    • 2018: ene-jun, jul-dic
    • 2019: ene-dic
    • 2020: ene-dic
  • Tapachula

    • 2011: feb
    • 2012: ene-oct
    • 2013: ene-dic
    • 2014: oct, nov
    • 2015: abr, may, oct, nov, dic
    • 2017: nov-dic
    • 2018: ene-jun, jul-dic
    • 2019: feb
    • 2020: ene-dic
  • Tuxtla Gutierrez

    • 2013: ene-dic
    • 2014: ene-dic
    • 2015: ene-dic
    • 2016: ene-dic
    • 2017: ene-dic
    • 2018: ene-jun, jul-dic
    • 2019: ene-dic
    • 2020: ene-dic

2 Limpieza de la base de datos

2.1 cargamos los datos

arriaga2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Arriaga 2018.csv", header = TRUE)

arriaga2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Arriaga 2019.csv", header = TRUE)

arriaga2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Arriaga 2020.csv", header = TRUE)

# Thu May 20 02:02:38 2021 ------------------------------

comitan2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Comitan 2018.csv", header = TRUE)

comitan2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Comitan 2019.csv", header = TRUE)

comitan2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Comitan 2020.csv", header = TRUE)

# Thu May 20 02:03:03 2021 ------------------------------

scdlc2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/scdlc 2018.csv", header = TRUE)

scdlc2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/scdlc 2019.csv", header = TRUE)

scdlc2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/scdlc 2020.csv", header = TRUE)

# Thu May 20 02:07:18 2021 ------------------------------

tapachula2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tapachula 2018.csv", header = TRUE)

tapachula2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tapachula 2019.csv", header = TRUE)

tapachula2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tapachula 2020.csv", header = TRUE)

# Thu May 20 02:08:44 2021 ------------------------------

tuxtla2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tuxtla 2018.csv", header = TRUE)

tuxtla2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tuxtla 2019.csv", header = TRUE)

tuxtla2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/Tuxtla 2020.csv", header = TRUE)

2.2 filtramos

a continuación se filtra por dia y mes respectivamente tomando la lluvia acumulada por dia, tengo en cuanta que se esta filtrando para meses con 30 dias y meses con 31 dias, donde

  • meses con 30 días son : Junio, Septiembre.

  • Meses con 31 días: Julio, Agosto, Octubre.

El procedimiento es el siguiente:

  1. Creamos un data frame vacio donde incluimos nuestra nueva columna (cum_rain).

  2. Ejecutamos un ciclo para los meses de 30 dias

  3. filtramos la base de datos por mes y dia, creamos la nueva variable de lluvia acumulada y seleccionamos el ultimo valor acumulado de la lluvia para ese dia respectivamente.

  4. si el numero de filas = 0 (esto debido porque algunos meses no contienen mediciones en días especificos, lo cual nos lleva a no tener lluvia acumulada en ese dia), añadimos una nueva fila con medicion cero para ese dia respectivamente.

  5. creamos nuestro data frame

2.2.1 Arriaga

library(tidyverse)

# arriaga 2018 seleccionando el maximo acumulado ------------------------------

n.arriaga2018.30 <- (arriaga2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- arriaga2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2018.30 <- rbind(n.arriaga2018.30,a)
        }
}

n.arriaga2018.31 <- (arriaga2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- arriaga2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2018.31 <- rbind(n.arriaga2018.31,a)
        }
}

n_arriaga2018 <- n.arriaga2018.30 %>% 
  union_all(n.arriaga2018.31)


# arriaga 2019 seleccionando el maximo acumulado ------------------------------

n.arriaga2019.30 <- (arriaga2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- arriaga2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2019.30 <- rbind(n.arriaga2019.30,a)
        }
}

n.arriaga2019.31 <- (arriaga2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- arriaga2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2019.31 <- rbind(n.arriaga2019.31,a)
        }
}

n_arriaga2019 <- n.arriaga2019.30 %>% 
  union_all(n.arriaga2019.31)

# arriaga 2020 seleccionando el maximo acumulado ------------------------------

n.arriaga2020.30 <- (arriaga2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- arriaga2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2020.30 <- rbind(n.arriaga2020.30,a)
        }
}

n.arriaga2020.31 <- (arriaga2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- arriaga2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Arriaga", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.arriaga2020.31 <- rbind(n.arriaga2020.31,a)
        }
}

n_arriaga2020 <- n.arriaga2020.30 %>% 
  union_all(n.arriaga2020.31)

2.2.2 Comitan

library(tidyverse)

# comitan 2018 seleccionando el maximo acumulado ------------------------------

n.comitan2018.30 <- (comitan2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- comitan2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2018.30 <- rbind(n.comitan2018.30,a)
        }
}

n.comitan2018.31 <- (comitan2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- comitan2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2018.31 <- rbind(n.comitan2018.31,a)
        }
}

n_comitan2018 <- n.comitan2018.30 %>% 
  union_all(n.comitan2018.31)


# comitan 2019 seleccionando el maximo acumulado ------------------------------

n.comitan2019.30 <- (comitan2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- comitan2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2019.30 <- rbind(n.comitan2019.30,a)
        }
}

n.comitan2019.31 <- (comitan2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- comitan2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2019.31 <- rbind(n.comitan2019.31,a)
        }
}

n_comitan2019 <- n.comitan2019.30 %>% 
  union_all(n.comitan2019.31)

# arriaga 2020 seleccionando el maximo acumulado ------------------------------

n.comitan2020.30 <- (comitan2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- comitan2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2020.30 <- rbind(n.comitan2020.30,a)
        }
}

n.comitan2020.31 <- (comitan2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- comitan2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Comitan", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.comitan2020.31 <- rbind(n.comitan2020.31,a)
        }
}

n_comitan2020 <- n.comitan2020.30 %>% 
  union_all(n.comitan2020.31)

2.2.3 San cristobal de las casas

library(tidyverse)

# scdlc 2018 seleccionando el maximo acumulado ------------------------------

n.scdlc2018.30 <- (scdlc2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- scdlc2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2018.30 <- rbind(n.scdlc2018.30,a)
        }
}

n.scdlc2018.31 <- (scdlc2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- scdlc2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2018.31 <- rbind(n.scdlc2018.31,a)
        }
}

n_scdlc2018 <- n.scdlc2018.30 %>% 
  union_all(n.scdlc2018.31)


# scdlc 2019 seleccionando el maximo acumulado ------------------------------

n.scdlc2019.30 <- (scdlc2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- scdlc2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2019.30 <- rbind(n.scdlc2019.30,a)
        }
}

n.scdlc2019.31 <- (scdlc2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- scdlc2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2019.31 <- rbind(n.scdlc2019.31,a)
        }
}

n_scdlc2019 <- n.scdlc2019.30 %>% 
  union_all(n.scdlc2019.31)

# arriaga 2020 seleccionando el maximo acumulado ------------------------------

n.scdlc2020.30 <- (scdlc2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- scdlc2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2020.30 <- rbind(n.scdlc2020.30,a)
        }
}

n.scdlc2020.31 <- (scdlc2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- scdlc2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "scdlc", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.scdlc2020.31 <- rbind(n.scdlc2020.31,a)
        }
}

n_scdlc2020 <- n.scdlc2020.30 %>% 
  union_all(n.scdlc2020.31)

2.2.4 Tapachula

# Tapachula 2018 seleccionando el maximo acumulado ------------------------------

n.tapachula2018.30 <- (tapachula2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tapachula2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2018.30 <- rbind(n.tapachula2018.30,a)
        }
}

n.tapachula2018.31 <- (tapachula2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tapachula2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2018.31 <- rbind(n.tapachula2018.31,a)
        }
}

n_tapachula2018 <- n.tapachula2018.30 %>% 
  union_all(n.tapachula2018.31)


# Tapachula 2019 seleccionando el maximo acumulado ------------------------------

n.tapachula2019.30 <- (tapachula2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tapachula2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2019.30 <- rbind(n.tapachula2019.30,a)
        }
}

n.tapachula2019.31 <- (tapachula2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tapachula2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2019.31 <- rbind(n.tapachula2019.31,a)
        }
}

n_tapachula2019 <- n.tapachula2019.30 %>% 
  union_all(n.tapachula2019.31)

# Tapachula 2020 seleccionando el maximo acumulado ------------------------------

n.tapachula2020.30 <- (tapachula2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tapachula2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2020.30 <- rbind(n.tapachula2020.30,a)
        }
}

n.tapachula2020.31 <- (tapachula2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tapachula2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tapachula", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tapachula2020.31 <- rbind(n.tapachula2020.31,a)
        }
}

n_tapachula2020 <- n.tapachula2020.30 %>% 
  union_all(n.tapachula2020.31)

2.2.5 Tuxtla

library(tidyverse)

# Tuxtla 2018 seleccionando el maximo acumulado ------------------------------

n.tuxtla2018.30 <- (tuxtla2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tuxtla2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2018.30 <- rbind(n.tuxtla2018.30,a)
        }
}

n.tuxtla2018.31 <- (tuxtla2018 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tuxtla2018 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2018, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2018.31 <- rbind(n.tuxtla2018.31,a)
        }
}

n_tuxtla2018 <- n.tuxtla2018.30 %>% 
  union_all(n.tuxtla2018.31)


# Tuxtla 2019 seleccionando el maximo acumulado ------------------------------

n.tuxtla2019.30 <- (tuxtla2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tuxtla2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2019.30 <- rbind(n.tuxtla2019.30,a)
        }
}

n.tuxtla2019.31 <- (tuxtla2019 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tuxtla2019 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2019, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2019.31 <- rbind(n.tuxtla2019.31,a)
        }
}

n_tuxtla2019 <- n.tuxtla2019.30 %>% 
  union_all(n.tuxtla2019.31)

# Tuxtla 2020 seleccionando el maximo acumulado ------------------------------

n.tuxtla2020.30 <- (tuxtla2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(6, 9)) {
    for (j in 1:30) {
          
        a <- tuxtla2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2020.30 <- rbind(n.tuxtla2020.30,a)
        }
}

n.tuxtla2020.31 <- (tuxtla2020 %>% add_column(cum_rain = NA))[NULL,]
for (i in c(7, 8, 10)) {
    for (j in 1:31) {
          
        a <- tuxtla2020 %>% 
              filter(Month == i & Day == j) %>% 
              mutate(cum_rain = cumsum(Rain)) %>% 
              slice_tail(n=1)
        
          if (nrow(a) == 0) {
              nd <-data.frame(16.23194,-93.90444, 0, "Tuxtla", j, i, 2020, 0)
              names(nd)<-names(a)
              a <- rbind(a, nd)
          }
        
      n.tuxtla2020.31 <- rbind(n.tuxtla2020.31,a)
        }
}

n_tuxtla2020 <- n.tuxtla2020.30 %>% 
  union_all(n.tuxtla2020.31)

2.3 base general

b2018 <- n_arriaga2018 %>% 
  union_all(n_comitan2018) %>% 
  union_all(n_scdlc2018) %>% 
  union_all(n_tapachula2018) %>% 
  union_all(n_tuxtla2018)

b2019 <- n_arriaga2019 %>% 
  union_all(n_comitan2019) %>% 
  union_all(n_scdlc2019) %>% 
  union_all(n_tapachula2019) %>% 
  union_all(n_tuxtla2019)

b2020 <- n_arriaga2020 %>% 
  union_all(n_comitan2020) %>% 
  union_all(n_scdlc2020) %>% 
  union_all(n_tapachula2020) %>% 
  union_all(n_tuxtla2020)


b2018 %>% 
  union_all(b2019) %>% 
  union_all(b2020) -> bg
library(tidyverse)
b2018 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/nd/b2018.csv", header = TRUE)

b2019 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/nd/b2019.csv", header = TRUE)

b2020 <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/nd/b2020.csv", header = TRUE)

bg <- read.csv("C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/datos/base/Chiapas 5/summer/data/nd/bg.csv", header = TRUE)


# b2018 <- b2018 %>% select(-Rain)
# b2019 <- b2019 %>% select(-Rain)
# b2020 <- b2020 %>% select(-Rain)
# bg <- bg %>% select(-Rain)

3 EDA fast

observemos un poco nuestras bases de datos, algunas estadisticas descriptivas

library(elucidate)
library(patchwork)


b2018 %>% 
  glimpse() %>% 
  describe(y = Rain)
> Rows: 765
> Columns: 8
> $ Latitud  <dbl> 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 1~
> $ Longitud <dbl> -93.90444, -93.90444, -93.90444, -93.90444, -93.90444, -93.90~
> $ Rain     <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> $ Station  <fct> Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga~
> $ Day      <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18~
> $ Month    <int> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6~
> $ year     <int> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2~
> $ cum_rain <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> # A tibble: 1 x 14
>   cases     n    na  p_na  mean    sd    se    p0   p25   p50   p75  p100  skew
>   <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1   765   765     0     0  4.41  9.18 0.332     0     0     0     4  57.4  2.90
> # ... with 1 more variable: kurt <dbl>
b2018 %>% 
  plot_density(x = Rain,
               title = "2018 basic density plot of Rain",
               fill = "lightseagreen") -> p1;p1

b2019 %>% 
  glimpse() %>% 
  describe(y = Rain)
> Rows: 765
> Columns: 8
> $ Latitud  <dbl> 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 1~
> $ Longitud <dbl> -93.90444, -93.90444, -93.90444, -93.90444, -93.90444, -93.90~
> $ Rain     <dbl> 16.00, 1.78, 5.59, 0.00, 0.00, 0.00, 0.00, 0.25, 17.27, 18.03~
> $ Station  <fct> Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga~
> $ Day      <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18~
> $ Month    <int> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6~
> $ year     <int> 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2~
> $ cum_rain <dbl> 16.00, 1.78, 5.59, 0.00, 0.00, 0.00, 0.00, 0.25, 17.27, 18.03~
> # A tibble: 1 x 14
>   cases     n    na  p_na  mean    sd    se    p0   p25   p50   p75  p100  skew
>   <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1   765   765     0     0  6.32  12.2 0.442     0     0   0.2     7  86.4  2.81
> # ... with 1 more variable: kurt <dbl>
b2019 %>% 
  plot_density(x = Rain,
               title = "2019 basic density plot of Rain",
               fill = "lightskyblue") -> p2;p2

b2020 %>% 
  glimpse() %>% 
  describe(y = Rain)
> Rows: 765
> Columns: 8
> $ Latitud  <dbl> 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 1~
> $ Longitud <dbl> -93.90444, -93.90444, -93.90444, -93.90444, -93.90444, -93.90~
> $ Rain     <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> $ Station  <fct> Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga~
> $ Day      <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18~
> $ Month    <int> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6~
> $ year     <int> 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2~
> $ cum_rain <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> # A tibble: 1 x 14
>   cases     n    na  p_na  mean    sd    se    p0   p25   p50   p75  p100  skew
>   <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1   765   765     0     0  6.45  14.6 0.526     0     0   0.2   5.6  98.8  3.57
> # ... with 1 more variable: kurt <dbl>
b2020 %>% 
  plot_density(x = Rain,
               title = "2020 basic density plot of Rain",
               fill = "olivedrab3") -> p3;p3

bg %>% 
  glimpse() %>% 
  describe(y = Rain)
> Rows: 2,295
> Columns: 8
> $ Latitud  <dbl> 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 16.23194, 1~
> $ Longitud <dbl> -93.90444, -93.90444, -93.90444, -93.90444, -93.90444, -93.90~
> $ Rain     <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> $ Station  <fct> Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga, Arriaga~
> $ Day      <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18~
> $ Month    <int> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6~
> $ year     <int> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2~
> $ cum_rain <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0~
> # A tibble: 1 x 14
>   cases     n    na  p_na  mean    sd    se    p0   p25   p50   p75  p100  skew
>   <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1  2295  2295     0     0  5.73  12.2 0.255     0     0   0.2   5.6  98.8  3.42
> # ... with 1 more variable: kurt <dbl>
bg %>% 
  plot_density(x = Rain,
               title = "(2018-2020) basic density plot general of Rain",
               fill = "salmon1") -> p4;p4

(p1 + p2)/(p3 + p4)

b2018 %>% 
  ggplot(aes(x = Day, y = Rain, color=factor(Month))) +
  # geom_point() +
  facet_wrap(~Station, scales="free") +
  theme_bw() +
  theme_minimal() +
  geom_line() + 
  ggtitle("Maximos para el 2018")

b2019 %>% 
  ggplot(aes(x = Day, y = Rain, color=factor(Month))) +
  # geom_point() +
  facet_wrap(~Station, scales="free") +
  theme_bw() +
  theme_minimal() +
  geom_line() + 
  ggtitle("Maximos para el 2019")

b2020 %>% 
  ggplot(aes(x = Day, y = Rain, color=factor(Month))) +
  # geom_point() +
  facet_wrap(~Station, scales="free") +
  theme_bw() +
  theme_minimal() +
  geom_line() + 
  ggtitle("Maximos para el 2020")

bg %>% 
  ggplot(aes(x = Day, y = Rain, color=factor(Month))) +
  # geom_point() +
  facet_wrap(~Station + year, scales="free") +
  theme_bw() +
  theme_minimal() +
  geom_line() + 
  ggtitle("Maximos para el 2018-2020")

4 grafica de los datos

Ahora creemos 3 graficos para cada año correspondiente de nuestro conjunto de datos, cargemos algunas librerias necesarias

La siguiente forma de mapear nuestro conjunto de datos obtenido, es de la siguiente forma, considere que esta forma no involucra leer un shape file, convertir los datos a tipo geodata y todas esas particularidades, eso es lo interesante y practico, aunque no descartamos hacerlo de la forma correspondiente.

Algo particular es que si necesitamos el shape file, solo para colocar el contorno del estado de chiapas, es por ello que debemos de leerlo.

cargamos algunas librerias

library(rgdal)
library(dplyr)
library(ggplot2)
library(leaflet)      # libreria para graficar mapas interactivos
library(sf)           # manejo de informacion geografica 
library(viridis)      # paletas de colores
library(RColorBrewer) # mas paletas de colores
library(patchwork)

a continuación leemos nuestro archivo shapefile, algo que debemos identificar del shapefile es que su proyeccion geografica no coincide con la proyeccion geografica del conjunto de daos a trabajar, es por ello que se necesita realizar una transformación en la proyección de nuestro shapefile, para llevarlo a la proyección habitual de longitud y latitud que se conoce.

my_spdf <- readOGR( 
  dsn= "C:/Users/David/OneDrive/Documentos/MMA/seminario de tesis 2/avances seminario/A2", 
  layer="ENTIDAD",
  verbose=FALSE
)

# trasformamos a el sistema de coordenadas habitual

my_spdf <- spTransform(my_spdf, CRS("+proj=longlat +datum=WGS84"))

y seleccionamos el estado de chiapas

my_spdf_c <- my_spdf[my_spdf$nombre == "CHIAPAS",]

podemos observar mediante un grafico que el estado seleccionado sea el correcto.

plot(my_spdf_c, col="#f2f2f2", bg="skyblue", lwd=0.25)

Ahora si estamos listos para realizar un grafico de nuestro conjunto de datos

b2018 %>% 
  ggplot() +
  geom_point(aes(x = Longitud, y = Latitud, colour = Rain),size =3)+
  borders(my_spdf_c)+
  coord_quickmap()+
  theme_test()

Agregando un poco mas de detalle podemos obtener un grafico mas detallado para cada año y general

library(ggrepel)

b2018 %>% 
  ggplot(aes(x = Longitud, y = Latitud)) +
  borders(my_spdf_c, fill = "antiquewhite1") +
  geom_point(aes(colour = Rain), size = 4) +
  scale_color_viridis_c(option = "plasma", trans = "sqrt",
                        oob = scales::squish) +
  coord_quickmap() +
  theme_test()  +
  xlab("Longitude") + ylab("Latitude") +
  ggtitle("Chiapas 2018", subtitle = "Precipitación media por hora") +
  theme(panel.grid.major = element_line(color = gray(0.5), linetype = "dashed", 
        size = 0.5), panel.background = element_rect(fill = "aliceblue")) +
  geom_text_repel(data = distinct(b2018, Longitud, .keep_all = TRUE), 
                  aes(x = Longitud, y = Latitud, label = Station),
                  box.padding   = 1, point.padding = 1, segment.color = 'grey50',
                  size = 4, point.size = 4, segment.size = 1) -> p5;p5

# unique(b2018$Station)
# distinct(b2018, Longitud, .keep_all = T)
# table(b2018$Latitud)
b2019 %>% 
  ggplot() +
  borders(my_spdf_c, fill = "antiquewhite1") +
  geom_point(aes(x = Longitud, y = Latitud, color = Rain, label=Station), size =4) +
  geom_text_repel(data = distinct(b2019, Station, .keep_all = TRUE), 
                  aes(x = Longitud, y = Latitud, label = Station),
                  box.padding   = 1, point.padding = 1, segment.color = 'grey50',
                  fontface = "bold", size = 4, point.size = 4, segment.size = 1)+
  coord_quickmap() +
  theme_test()  +
  scale_color_viridis_c(option = "plasma", trans = "sqrt") +
  xlab("Longitude") + ylab("Latitude") +
  ggtitle("Chiapas 2019", subtitle = "Precipitación media por hora") +
  theme(panel.grid.major = element_line(color = gray(0.5), linetype = "dashed", size = 0.5), 
        panel.background = element_rect(fill = "aliceblue")) -> p6;p6


b2020 %>% 
ggplot() +
  borders(my_spdf_c, fill = "antiquewhite1") +
  geom_point(aes(x = Longitud, y = Latitud, color = Rain, label = Station), size =4) +
  geom_text_repel(data = distinct(b2020, Station, .keep_all = TRUE), 
                  aes(x = Longitud, y = Latitud, label = Station),
                  box.padding   = 1, point.padding = 1, segment.color = 'grey50',
                  fontface = "bold", size = 4, point.size = 4, segment.size = 1)+  
  coord_quickmap() +
  theme_test()  +
  scale_color_viridis_c(option = "plasma", trans = "sqrt") +
  xlab("Longitude") + ylab("Latitude") +
  ggtitle("Chiapas 2020", subtitle = "Precipitación media por hora") +
  theme(panel.grid.major = element_line(color = gray(0.5), linetype = "dashed", 
        size = 0.5), panel.background = element_rect(fill = "aliceblue")) -> p7;p7

bg %>% 
ggplot() +
  borders(my_spdf_c, fill = "antiquewhite1") +
  geom_point(aes(x = Longitud, y = Latitud, color = Rain, label=Station), size =4) +
  geom_text_repel(data = distinct(b2020, Station, .keep_all = TRUE), 
                  aes(x = Longitud, y = Latitud, label = Station),
                  box.padding   = 1, point.padding = 1, segment.color = 'grey50',
                  fontface = "bold", size = 4, point.size = 4, segment.size = 1)+    
  coord_quickmap() +
  theme_test()  +
  scale_color_viridis_c(option = "plasma", trans = "sqrt") +
  xlab("Longitude") + ylab("Latitude") +
  ggtitle("Chiapas 2018-2020", subtitle = "Precipitación media por hora") +
  theme(panel.grid.major = element_line(color = gray(0.5), linetype = "dashed", 
        size = 0.5), panel.background = element_rect(fill = "aliceblue")) -> p8;p8

(p5 + p6)/(p7 + p8)

5 prueba estadistica formal para verificar si mis datos son de GEV

Algo importante es determinar si mi conjunto de datos sigue una GEVD, esto se realiza de la siguiente forma.

¿Que realiza este paquete?

Calcula el estadístico de prueba y el valor p de la prueba de Cramer-von Mises y Anderson Darling para algunas funciones de distribución continua propuestas por Chen y Balakrishnan (1995) [http://asq.org/qic/display-item/index.html?item= 11407]. Además de nuestras funciones de distribución clásicas aquí, calculamos la prueba de bondad de ajuste (GoF) para el conjunto de datos que sigue la función de distribución de valor extremo, sin recordar la fórmula de las funciones de distribución/densidad. Calcula el valor en riesgo (VaR) y el VaR promedio son otros factores de riesgo importantes que se estiman mediante el uso de funciones de distribución bien conocidas. Pflug y Romisch (2007, ISBN: 9812707409) es una buena referencia para estudiar las propiedades de las medidas de riesgo.

library(gnFit)
library(fExtremes)
library(extRemes)
library(ismev)

Para probar H0: X1,. . . , Xn es una muestra aleatoria de una distribución continua con función de distribución acumulativa F (x; θ), donde se conoce la forma de F pero se desconoce θ. Primero estimamos θ por \(θ^∗\) (por ejemplo, método de estimación de máxima verosimilitud). A continuación, calculamos vi = F (xi, θ∗), donde los xi están en orden ascendente.

5.1 con mis datos

seleccionemos los valores mayores a 29 de la precipitación por hora esto con respecto a información que se menciono al comienzo.

nd <- bg %>% 
  dplyr::select(Rain) %>% 
  dplyr::filter(Rain > 30)

# nd_m = gevSim(model = list(xi = 0.25, mu = 0 , beta = 1), n = 1000)
# fit1  = gevFit(x1, type = "mle") 
nd_m <- gev.fit(as.vector(as.numeric(as.matrix(nd))))
> $conv
> [1] 0
> 
> $nllh
> [1] 484.0994
> 
> $mle
> [1] 37.3217329  7.4037727  0.5305033
> 
> $se
> [1] 0.8172385 0.7893880 0.1191109
gev.diag(nd_m)

# fit1@fit[c(6, 7, 3, 4)]
gnfit(as.numeric(as.matrix(nd)), "gev", pr = nd_m$mle)
> Test of Hypothesis for gev distribution
> Cramer-von Misses Statistics:  0.0784   P-Value:  0.2174
> Anderson-Darling Statistics:   0.6485   P-Value:  0.09065

nd_m1 <- gevFit(nd, type = "mle")
print(nd_m1)
> 
> Title:
>  GEV Parameter Estimation 
> 
> Call:
>  gevFit(x = nd, type = "mle")
> 
> Estimation Type:
>   gev mle 
> 
> Estimated Parameters:
>         xi         mu       beta 
>  0.5304988 37.3221090  7.4043417 
> 
> Description
>   Thu Jun 10 06:53:21 2021
## summary -
   # Summarize Results:
   par(mfcol = c(2, 2))
   summary(nd_m1)
> 
> Title:
>  GEV Parameter Estimation 
> 
> Call:
>  gevFit(x = nd, type = "mle")
> 
> Estimation Type:
>   gev mle 
> 
> Estimated Parameters:
>         xi         mu       beta 
>  0.5304988 37.3221090  7.4043417 
> 
> Standard Deviations:
>         xi        mu      beta 
> 0.1191180 0.8172779 0.7894815 
> 
> Log-Likelihood Value:
>   484.0994 
> 
> Type of Convergence:
>   0 
> 
> Description
>   Thu Jun 10 06:53:21 2021

6 ajuste de Davison, A.C., Padoan, S.A. and Ribatet

La siguiente metodologia es conforme al ajuste de Davison, A.C., Padoan, S.A. and Ribatet.

La función para incorporar el componente temporal y spatial a una DVEG es la función latent de la libreria SpatialExtremes, la cual indica lo siguiente:

latent: Modelos jerárquicos bayesianos para extremos espaciales

Descripción

Esta función genera una cadena de Markov a partir de un modelo jerárquico bayesiano para bloques máximos asumiendo independencia condicional.

Uso

latent(data, coord, cov.mod = "powexp", loc.form, scale.form,
shape.form, marg.cov = NULL, hyper, prop, start, n = 5000, thin = 1,
burn.in = 0, use.log.link = FALSE)

Argumentos

data: Una matriz que representa los datos. Cada columna corresponde a una ubicación.

coord: Una matriz que da las coordenadas de cada ubicación. Cada fila corresponde a una ubicación.

cov.model: Cadena de caracteres correspondiente al modelo de covarianza de los procesos latentes gaussianos. Debe ser uno de “gauss” para el modelo de Smith; “whitmat”, “cauchy”, “powexp” o “bessel” o para las familias de correlación Whittle-Matern, Cauchy, Powered Exponential y Bessel.

loc.form, scale.form, shape.form: Fórmulas R que definen los modelos espaciales para los parámetros GEV. Consulte la sección Detalles.

mar.cov: Matriz con columnas nombradas que dan covariables adicionales para las medias de los procesos latentes. Si es NULL, no se utilizan covariables adicionales.

hyper: Una lista con nombre que especifica los hiperparámetros

covariables: Matriz con columnas nombradas que dan las covariables requeridas para los modelos de parámetros de GEV.

prop:Una lista con nombre que especifica los tamaños de salto cuando se necesita un movimiento de Metropolis-Hastings

start: Una lista con nombre que proporciona los valores iniciales

n: La longitud efectiva de la cadena de Markov simulada, es decir, una vez descartado el período de quemado y después del adelgazamiento.

thin: Un número entero que especifica la longitud de adelgazamiento. El valor predeterminado es 1, es decir, sin adelgazamiento

burn.in: Un número entero que especifica el período de quemado. El valor predeterminado es 0, es decir, sin quemado

use.log.link: Un entero. ¿Debería utilizarse una función de liga logarítmico para los parámetros de la escala GEV, es decir, suponiendo que los parámetros de la escala GEV se extraen de un proceso logarítmico normal en lugar de un proceso gaussiano?

Detalles

Esta función genera una cadena de Markov a partir del siguiente modelo. Para cada \(x \in R_d\), suponga que \(Y (x)\) es GEV distribuido cuyos parámetros \(\{µ (x); σ(x); ξ (x)\}\) varían suavemente para \(x \in R^d\) de acuerdo con un proceso estocástico \(S (x)\). Suponemos que los procesos para cada parámetro de GEV son procesos gaussianos mutuamente independientes. Por ejemplo, tomamos como parámetro de ubicación \(µ (x)\)

\[ \mu(x)=f_{\mu(x)}\left(x ; \beta_{\mu}\right)+S_{\mu}\left(x ; \alpha_{\mu}, \lambda_{\mu}, \kappa_{\mu}\right) \]

donde \(f_µ\) es una función determinista que depende de los parámetros de regresión \(β_µ\), y \(S_µ\) es un proceso gaussiano estacionario de media cero con una función de covarianza prescrita con umbral \(α_µ\), rango \(λ_µ\) y parámetros de forma \(κ_µ\). Se utilizan formulaciones similares para los parámetros de escala \(σ (x)\) y forma \(ξ (x)\). Luego, condicionado a los valores de los tres procesos gaussianos en los sitios \((x_1,..., x_K)\), se supone que los máximos siguen distribuciones GEV

\[ Y_{i}\left(x_{j}\right) \mid\left\{\mu\left(x_{j}\right), \sigma\left(x_{j}\right), \xi\left(x_{j}\right)\right\} \sim \operatorname{GEV}\left\{\mu\left(x_{j}\right), \sigma\left(x_{j}\right), \xi\left(x_{j}\right)\right\}, \]

independientemente para cada ubicación \((x_1,..., x_K)\).

Se debe definir una densidad a priori conjunta para los umbrales, rangos y parámetros de formas de las funciones de covarianza, así como para los parámetros de regresión \(β_µ\), \(β_σ\) y \(β_ξ\). Siempre que sea posible, se utilizan a priori conjugados, tomando distribuciones Gamma inversa independiente y normal multivariante para los umbrales y los parámetros de regresión. No existe un conjugado a priori para \(λ\) y \(κ\), por lo que se supone una distribución Gamma.

En consecuencia, hyper es una lista con nombre con componentes con nombre.

Como no existe una a priori conjugado para los parámetros de GEV y los parámetros de rango y forma de las funciones de covarianza, se necesitan los pasos de Metropolis-Hastings. Las propuestas \(θ_{prop}\) se extraen de una densidad de propuesta \(q(· | θ_{cur}, s)\) donde \(θ_{cur}\) es el estado actual del parámetro y s es un parámetro de la densidad de propuesta a definir. Estas propuestas están impulsadas por prop, que es una lista con tres componentes nombrados

Si uno quiere mantener fijo un parámetro, esto se puede hacer estableciendo un tamaño de salto nulo, entonces el parámetro se mantendrá fijo en su valor inicial.

Finalmente, el star debe ser una lista con nombre con 4 componentes con nombre

Valor Una lista

Advertencia Esta función puede llevar mucho tiempo y hace un uso intensivo de las rutinas BLAS, por lo que es (¡mucho!) Más rápida si tiene un BLAS optimizado. Los valores iniciales nunca se almacenarán en la cadena de Markov generada incluso cuando burn.in = 0.

6.1 Modelo

Recordando que

\[ Y_{i}\left(x_{j}\right) \mid\left\{\mu\left(x_{j}\right), \sigma\left(x_{j}\right), \xi\left(x_{j}\right)\right\} \sim \operatorname{GEV}\left\{\mu\left(x_{j}\right), \sigma\left(x_{j}\right), \xi\left(x_{j}\right)\right\}, \]

independientemente para cada ubicación \((x_1,..., x_K)\).

donde

\[ \mu(x)=f_{\mu(x)}\left(x ; \beta_{\mu}\right)+S_{\mu}\left(x ; \alpha_{\mu}, \lambda_{\mu}, \kappa_{\mu}\right) \]

\[ \sigma(x)=f_{\sigma(x)}\left(x ; \beta_{\sigma}\right)+S_{\sigma}\left(x ; \alpha_{\sigma}, \lambda_{\sigma}, \kappa_{\mu}\right) \]

\[ \xi(x)=f_{\xi(x)}\left(x ; \beta_{\xi}\right)+S_{\xi}\left(x ; \alpha_{\xi}, \lambda_{\xi}, \kappa_{\xi}\right) \]

Ahora concentrandonos en \(\mu(x)\), note que

\[ \mu(x)=f_{\mu(x)}\left(x ; \beta_{\mu}\right)+S_{\mu}\left(x ; \alpha_{\mu}, \lambda_{\mu}, \kappa_{\mu}\right) \]

conforme a

Banerjee, S., Carlin, B. P., and Gelfand, A. E. (2004). Hierarchical Modeling and Analysis for Spatial Data. Chapman & Hall/CRC, New York.

Casson, E. and Coles, S. (1999) Spatial regression models for extremes. Extremes 1,449–468.

Cooley, D., Nychka, D. and Naveau, P. (2007) Bayesian spatial modelling of extreme precipitation

return levels Journal of the American Statistical Association 102:479, 824–840.

Davison, A.C., Padoan, S.A. and Ribatet, M. Statistical Modelling of Spatial Extremes. Submitted.

suguieren que los parámetros de umbral, rango y forma.

\[ \alpha, \lambda, \kappa \sim p(\alpha, \lambda, \kappa) \]

en particular el umbral

\[ \alpha \sim IG(a_1, b_1) \] el rango

\[ \lambda, \kappa \sim G(a_{2,3}, b_{2,3}) \] ademas

\[ \beta \sim N(\boldsymbol{\mu},\boldsymbol{\Sigma}) \] ## Aplicación

Ilustramos la discusión anterior usando los datos de precipitación máxima anual descritos. Por lo que ajustamos la distribución de valores extremos generalizados, utilizando parámetros descritos por las superficies de tendencia

\[ \begin{array}{l} \eta(x)=\beta_{0, \eta}+\beta_{1, \eta} \operatorname{lon}(x)+\beta_{2, \eta} \operatorname{lat}(x), \\ \tau(x)=\beta_{0, \tau}+\beta_{1, \tau} \operatorname{lon}(x)+\beta_{2, \tau} \operatorname{lat}(x), \\ \xi(x)=\beta_{0, \xi} \end{array} \] donde lon (x) y lat (x) son la longitud y latitud de las estaciones en las que se observan los datos. La estructura marginal de las ecuaciones anteriores se eligió utilizando el CLIC y los valores de verosimilitud obtenidos al ajustar una amplia gama de modelos plausibles.

Recuerde que el CLIC es:

(La selección del modelo se efectúa minimizando el criterio de información de verosimilitud compuesta, que tiene propiedades análogas a las de AIC y TIC)

\[ CLIC = -2 \ell_{p}(\hat{\vartheta})+2 \operatorname{tr}\left\{J^{-1}(\hat{\vartheta}) K(\hat{\vartheta})\right\} \]

6.2 code

bg <- bg %>% 
  dplyr::filter(Rain > 30)

bg %>% 
  plot_density(x = Rain,
               title = "(2018-2020) basic density plot general of cum_rain",
               fill = "salmon1")

table(bg$Station)
> 
>   Arriaga   Comitan     scdlc Tapachula    Tuxtla 
>        11        25         0        62        27
library(SpatialExtremes)
## Not run:
## Generate realizations from the model
n.site <- 4 # numero de sitios muestreados

n.obs  <- 11 # numero de observaciones tomada en cada sitio muestreado

coord  <- bg %>%                    # creamos la matrix de coordenadas
  select(Longitud, Latitud) %>%       # esta matrix de coordenadas solo incluye el
  unique()                            # numero de sitios donde se muestreo

coord  <- cbind(lon = coord$Longitud, lat = coord$Latitud) # matrix de coordenadas
# sin mediciones repetidas
# class(coord)
# coord <- cbind(lon = runif(n.site, -10, 10), lat = runif(n.site, -10 , 10))

# creamos un proceso gaussiano para cada parametro  de la GEV, esta parte se deja
# a elección del autor elegirlo.

gp.loc   <- SpatialExtremes::rgp(1, coord, "powexp", sill = 0.01, range = 10, smooth = 1)
gp.scale <- SpatialExtremes::rgp(1, coord, "powexp", sill = 0.001, range = 15, smooth = 1)
gp.shape <- SpatialExtremes::rgp(1, coord, "powexp", sill = 0.001, range = 20, smooth = 1)


# locs   <- 26 + 0.5 * coord[,"lon"] + gp.loc
# scales <- 10 + 0.2 * coord[,"lat"] + gp.scale
# shapes <- 0.15 + gp.shape


# Estimated Parameters:
#         xi         mu       beta 
#  0.3944641 34.1387472  4.7882714 

data <- matrix(NA, n.obs, n.site)
# 
# for (i in 1:n.site)
#   data[,i] <- SpatialExtremes::rgev(n.obs, locs[i], scales[i], shapes[i])
dim(bg)
> [1] 125   8
table(bg$Station)
> 
>   Arriaga   Comitan     scdlc Tapachula    Tuxtla 
>        11        25         0        62        27
data[,1]  <-bg %>% 
  dplyr::select(Rain, Station) %>% 
  dplyr::filter(Station == "Arriaga") %>% 
  # slice(1:5) %>% 
  dplyr::select(Rain) %>% 
  dplyr::arrange(-Rain) %>% 
  slice(1:11) %>% 
  as.matrix()
data[,2]  <-bg %>% 
  dplyr::select(Rain, Station) %>% 
  dplyr::filter(Station == "Comitan") %>% 
  # slice(1:5) %>% 
  select(Rain) %>% 
  arrange(-Rain) %>% slice(1:11) %>% 
  as.matrix()
# data[,3]  <- bg %>% 
#   dplyr::select(cum_rain, Station) %>% 
#   dplyr::filter(Station == "scdlc") %>% 
#   # slice(1:5) %>% 
#   select(cum_rain) %>% 
#   arrange(-cum_rain) %>% # slice(1:61) %>% 
#   as.matrix()
data[,3]  <- bg %>% 
  dplyr::select(Rain, Station) %>% 
  dplyr::filter(Station == "Tapachula") %>% 
  # slice(1:5) %>% 
  select(Rain) %>% 
  arrange(-Rain) %>% slice(1:11) %>% 
  as.matrix()
data[,4]  <- bg %>% 
  dplyr::select(Rain, Station) %>% 
  dplyr::filter(Station == "Tuxtla") %>% 
  # slice(1:5) %>% 
  select(Rain) %>% 
  arrange(-Rain) %>%  slice(1:11) %>% 
  as.matrix()

# b2018[b2018$Station == "Arriaga", 3]
# data[,5] <- b2018[b2018$Station == "tuxtlag", 3]
# data[,1]  <- b2018[1:10,3]

# loc.form   <- y ~ lon
# scale.form <- y ~ lat
# shape.form <- y ~ 1

loc.form   <- y ~ 1
scale.form <- y ~ 1
shape.form <- y ~ 1

hyper <- list()
hyper$sills     <- list(loc = c(1,8), 
                        scale = c(1,1), 
                        shape = c(1,0.02))
hyper$ranges    <- list(loc = c(2,20), 
                        scale = c(1,5), 
                        shape = c(1, 10))
hyper$smooths   <- list(loc = c(1,1/3), 
                        scale = c(1,1/3), 
                        shape = c(1, 1/3))
hyper$betaMeans <- list(loc = 9, 
                        scale = 6, 
                        shape = 2)
hyper$betaIcov  <- list(loc =   solve(diag(c(10), 1, 1)),
                        scale = solve(diag(c(10), 1, 1)),
                        shape = solve(diag(c(0.13), 1, 1)))
## We will use an exponential covariance function so the jump sizes for
## the shape parameter of the covariance function are null.

prop <- list(gev = c(1.2, 0.08, 0.08), ranges = c(0.7, 0.8, 0.7), smooths = c(0,0,0))

start <- list(sills = c(4, .36, 0.009), 
              ranges = c(24, 17, 16), 
              smooths= c(1, 1, 1), 
              beta = list(loc = c(24), 
                          scale = c(7.31),
                          shape = c(0.54)))

# Estimated Parameters:
#   xi         mu       beta 
# 0.5304988 37.3221090  7.4043417 

mc1 <- latent(data, coord, 
             loc.form = loc.form, 
             scale.form = scale.form,
             shape.form = shape.form, 
             hyper = hyper, 
             prop = prop, 
             start = start,
             n = 10000, 
             burn.in = 5000, 
             thin = 15)
mc1
> Effective length: 10000 
>          Burn-in: 5000 
>         Thinning: 15 
>    Effective NoP: 5.153898 
>              DIC: 343.2105 
> 
>   Regression Parameters:
>       Location Parameters:
>            lm1   
> ci.lower    3.041
> post.mean   9.277
> ci.upper   15.482
> 
>          Scale Parameters:
>            lm1   
> ci.lower    4.188
> post.mean   7.522
> ci.upper   11.185
> 
>          Shape Parameters:
>            lm1   
> ci.lower   0.6902
> post.mean  1.4972
> ci.upper   2.3470
> 
> 
>   Latent Parameters:
>       Location Parameters:
>         Covariance family: powexp 
>            sill       range      smooth   
> ci.lower     539.082      3.072      1.000
> post.mean   3925.321     22.432      1.000
> ci.upper   16264.193     70.049      1.000
> 
>       Scale Parameters:
>      Covariance family: powexp 
>            sill     range    smooth 
> ci.lower    0.2681   0.1143   1.0000
> post.mean   3.1899   5.0868   1.0000
> ci.upper   17.1956  18.9550   1.0000
> 
>       Shape Parameters:
>      Covariance family: powexp 
>            sill      range     smooth  
> ci.lower    0.01019   0.85700   1.00000
> post.mean   0.72350  12.51019   1.00000
> ci.upper    3.81260  41.73149   1.00000
mc2 <- latent(data, coord, 
             loc.form = loc.form, 
             scale.form = scale.form,
             shape.form = shape.form, 
             hyper = hyper, 
             prop = prop, 
             start = start,
             n = 10000, 
             burn.in = 5000, 
             thin = 15)
mc2
> Effective length: 10000 
>          Burn-in: 5000 
>         Thinning: 15 
>    Effective NoP: 5.153898 
>              DIC: 343.2105 
> 
>   Regression Parameters:
>       Location Parameters:
>            lm1   
> ci.lower    3.041
> post.mean   9.277
> ci.upper   15.482
> 
>          Scale Parameters:
>            lm1   
> ci.lower    4.188
> post.mean   7.522
> ci.upper   11.185
> 
>          Shape Parameters:
>            lm1   
> ci.lower   0.6902
> post.mean  1.4972
> ci.upper   2.3470
> 
> 
>   Latent Parameters:
>       Location Parameters:
>         Covariance family: powexp 
>            sill       range      smooth   
> ci.lower     539.082      3.072      1.000
> post.mean   3925.321     22.432      1.000
> ci.upper   16264.193     70.049      1.000
> 
>       Scale Parameters:
>      Covariance family: powexp 
>            sill     range    smooth 
> ci.lower    0.2681   0.1143   1.0000
> post.mean   3.1899   5.0868   1.0000
> ci.upper   17.1956  18.9550   1.0000
> 
>       Shape Parameters:
>      Covariance family: powexp 
>            sill      range     smooth  
> ci.lower    0.01019   0.85700   1.00000
> post.mean   0.72350  12.51019   1.00000
> ci.upper    3.81260  41.73149   1.00000
mc3 <- latent(data, coord, 
             loc.form = loc.form, 
             scale.form = scale.form,
             shape.form = shape.form, 
             hyper = hyper, 
             prop = prop, 
             start = start,
             n = 10000, 
             burn.in = 5000, 
             thin = 15)
mc3
> Effective length: 10000 
>          Burn-in: 5000 
>         Thinning: 15 
>    Effective NoP: 5.153898 
>              DIC: 343.2105 
> 
>   Regression Parameters:
>       Location Parameters:
>            lm1   
> ci.lower    3.041
> post.mean   9.277
> ci.upper   15.482
> 
>          Scale Parameters:
>            lm1   
> ci.lower    4.188
> post.mean   7.522
> ci.upper   11.185
> 
>          Shape Parameters:
>            lm1   
> ci.lower   0.6902
> post.mean  1.4972
> ci.upper   2.3470
> 
> 
>   Latent Parameters:
>       Location Parameters:
>         Covariance family: powexp 
>            sill       range      smooth   
> ci.lower     539.082      3.072      1.000
> post.mean   3925.321     22.432      1.000
> ci.upper   16264.193     70.049      1.000
> 
>       Scale Parameters:
>      Covariance family: powexp 
>            sill     range    smooth 
> ci.lower    0.2681   0.1143   1.0000
> post.mean   3.1899   5.0868   1.0000
> ci.upper   17.1956  18.9550   1.0000
> 
>       Shape Parameters:
>      Covariance family: powexp 
>            sill      range     smooth  
> ci.lower    0.01019   0.85700   1.00000
> post.mean   0.72350  12.51019   1.00000
> ci.upper    3.81260  41.73149   1.00000
## End(Not run)

# a <- summary(mc)
# 
# a
# head(mc$chain.loc)
# head(mc$chain.scale)
# head(mc$chain.shape)
# head(mc$loc.dsgn.mat)
# head(mc$scale.dsgn.mat)
# head(mc$shape.dsgn.mat)

# tidybayes::add_residual_draws(mc$chain.loc[,6:10])

# mod1_sim <- coda::coda.samples(model = mc, 
#                          variable.names = chain.loc,
                         # n.iter = 5000)

dsgn.mat The design matrix.

sill = umbral

ranges = rango

smooths = forma

6.2.1 diagnosticos

Un vector de longitud 3 que devuelve el DIC, el número efectivo de parámetros eNoP y una estimación de la desviación esperada Dbar.

library(broom)
library(coda)
library(broom.mixed)
library(brms)
library(bayesplot)

parametro de localización

mc1$chain.loc <- as.data.frame(mc1$chain.loc) %>% 
  mutate(chain = 1)
mc2$chain.loc <- as.data.frame(mc2$chain.loc) %>% 
  mutate(chain = 2)
mc3$chain.loc <- as.data.frame(mc3$chain.loc) %>% 
  mutate(chain = 3)

mc.loc <-  mc1$chain.loc %>% 
  union_all(mc2$chain.loc) %>% union_all(mc3$chain.loc)

post <- posterior_samples(mc.loc, add_chain = T)
mcmc_dens_overlay(post)

post %>% 
  select(lm1, sill, range, loc1, loc2, loc3, loc4) %>% 
  mcmc_acf()

post %>% 
  select(lm1, sill, range, loc1, loc2, loc3, loc4) %>% 
  mcmc_trace()

post %>% 
  select(lm1, sill, range, loc1, loc2, loc3, loc4) %>% 
  mcmc_dens()

post %>% select(lm1) %>% mcmc_trace()

library(coda)

coda::raftery.diag(posterior_samples(post))
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    2        3834  3746          1.02     
>  sill   2        3802  3746          1.01     
>  range  2        3897  3746          1.04     
>  smooth <NA>     <NA>  3746            NA     
>  loc1   6        8416  3746          2.25     
>  loc2   4        5123  3746          1.37     
>  loc3   6        6577  3746          1.76     
>  loc4   4        4673  3746          1.25     
>  chain  69075    69075 3746         18.40
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.loc[,c(-4,-9)]), 
#                             as.mcmc(mc2$chain.loc[,c(-4,-9)]), 
#                             as.mcmc(mc3$chain.loc[,c(-4,-9)])))
# 
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.loc[,1]), 
#                             as.mcmc(mc2$chain.loc[,1]), 
#                             as.mcmc(mc3$chain.loc[,1])))

BMu1.mcmc<-mcmc.list(as.mcmc(mc1$chain.loc[,c(-4,-9)]), 
                     as.mcmc(mc2$chain.loc[,c(-4,-9)]),
                     as.mcmc(mc3$chain.loc[,c(-4,-9)]))

summary(BMu1.mcmc)
> 
> Iterations = 1:10000
> Thinning interval = 1 
> Number of chains = 3 
> Sample size per chain = 10000 
> 
> 1. Empirical mean and standard deviation for each variable,
>    plus standard error of the mean:
> 
>           Mean       SD Naive SE Time-series SE
> lm1      9.277    3.176  0.01833        0.01834
> sill  3925.321 5354.748 30.91565       31.56062
> range   22.432   18.223  0.10521        0.11477
> loc1    36.855    1.952  0.01127        0.02371
> loc2    65.122    2.091  0.01207        0.02460
> loc3    61.734    2.699  0.01558        0.04719
> loc4    47.641    2.207  0.01274        0.03690
> 
> 2. Quantiles for each variable:
> 
>          2.5%      25%      50%     75%    97.5%
> lm1     3.041    7.172    9.291   11.40    15.48
> sill  539.082 1371.300 2450.159 4504.52 16264.19
> range   3.072    9.594   17.010   29.87    70.05
> loc1   33.035   35.598   36.812   38.09    40.83
> loc2   61.047   63.847   65.080   66.36    69.45
> loc3   56.627   60.165   61.614   63.16    67.43
> loc4   43.693   46.183   47.493   48.92    52.39
xyplot(BMu1.mcmc)

densityplot(BMu1.mcmc)                             #Densidades

plot(BMu1.mcmc)

# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)

coda::acfplot(BMu1.mcmc)

# gelman.diag(BMu1.mcmc)
# 
# gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
> [[1]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>      lm1     sill    range     loc1     loc2     loc3     loc4 
>  0.98817  0.39513  0.53475 -0.21566 -0.09909  1.20355  0.99870 
> 
> 
> [[2]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>      lm1     sill    range     loc1     loc2     loc3     loc4 
>  0.98817  0.39513  0.53475 -0.21566 -0.09909  1.20355  0.99870 
> 
> 
> [[3]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>      lm1     sill    range     loc1     loc2     loc3     loc4 
>  0.98817  0.39513  0.53475 -0.21566 -0.09909  1.20355  0.99870
#geweke.plot(BMu1.mcmc)
raftery.diag(BMu1.mcmc)
> [[1]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                              
>        Burn-in  Total Lower bound  Dependence
>        (M)      (N)   (Nmin)       factor (I)
>  lm1   2        3834  3746         1.02      
>  sill  2        3802  3746         1.01      
>  range 2        3897  3746         1.04      
>  loc1  5        5624  3746         1.50      
>  loc2  4        5123  3746         1.37      
>  loc3  6        6577  3746         1.76      
>  loc4  4        4674  3746         1.25      
> 
> 
> [[2]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                              
>        Burn-in  Total Lower bound  Dependence
>        (M)      (N)   (Nmin)       factor (I)
>  lm1   2        3834  3746         1.02      
>  sill  2        3802  3746         1.01      
>  range 2        3897  3746         1.04      
>  loc1  5        5624  3746         1.50      
>  loc2  4        5123  3746         1.37      
>  loc3  6        6577  3746         1.76      
>  loc4  4        4674  3746         1.25      
> 
> 
> [[3]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                              
>        Burn-in  Total Lower bound  Dependence
>        (M)      (N)   (Nmin)       factor (I)
>  lm1   2        3834  3746         1.02      
>  sill  2        3802  3746         1.01      
>  range 2        3897  3746         1.04      
>  loc1  5        5624  3746         1.50      
>  loc2  4        5123  3746         1.37      
>  loc3  6        6577  3746         1.76      
>  loc4  4        4674  3746         1.25
# heidel.diag(BMu1.mcmc)

parametro de escala

mc1$chain.scale <- as.data.frame(mc1$chain.scale) %>% 
  mutate(chain = 1)
mc2$chain.scale <- as.data.frame(mc2$chain.scale) %>% 
  mutate(chain = 2)
mc3$chain.scale <- as.data.frame(mc3$chain.scale) %>% 
  mutate(chain = 3)

mc.loc <-  mc1$chain.scale %>% 
  union_all(mc2$chain.scale) %>% union_all(mc3$chain.scale)

post <- posterior_samples(mc.loc, add_chain = T)
mcmc_dens_overlay(post)

post %>% 
  select(lm1, sill, range, scale1, scale2, scale3, scale4) %>% 
  mcmc_acf()

post %>% 
  select(lm1, sill, range, scale1, scale2, scale3, scale4) %>% 
  mcmc_trace()

post %>% 
  select(lm1, sill, range, scale1, scale2, scale3, scale4) %>% 
  mcmc_dens()

post %>% select(lm1) %>% mcmc_trace()

library(coda)

coda::raftery.diag(posterior_samples(post))
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    6        11982 3746          3.200    
>  sill   2        3680  3746          0.982    
>  range  6        6349  3746          1.690    
>  smooth <NA>     <NA>  3746             NA    
>  scale1 16       21284 3746          5.680    
>  scale2 12       12592 3746          3.360    
>  scale3 20       22800 3746          6.090    
>  scale4 16       22528 3746          6.010    
>  chain  69075    69075 3746         18.400
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.scale[,c(-4,-9)]), 
#                             as.mcmc(mc2$chain.scale[,c(-4,-9)]), 
#                             as.mcmc(mc3$chain.scale[,c(-4,-9)])))
# 
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.scale[,1]), 
#                             as.mcmc(mc2$chain.scale[,1]), 
#                             as.mcmc(mc3$chain.scale[,1])))

BMu1.mcmc<-mcmc.list(as.mcmc(mc1$chain.scale[,c(-4,-9)]), 
                     as.mcmc(mc2$chain.scale[,c(-4,-9)]),
                     as.mcmc(mc3$chain.scale[,c(-4,-9)]))

summary(BMu1.mcmc)
> 
> Iterations = 1:10000
> Thinning interval = 1 
> Number of chains = 3 
> Sample size per chain = 10000 
> 
> 1. Empirical mean and standard deviation for each variable,
>    plus standard error of the mean:
> 
>         Mean    SD Naive SE Time-series SE
> lm1    7.522 1.766 0.010195        0.03012
> sill   3.190 8.657 0.049979        0.06900
> range  5.087 5.085 0.029359        0.03656
> scale1 7.470 1.723 0.009948        0.03438
> scale2 7.721 1.739 0.010041        0.03534
> scale3 8.007 1.794 0.010358        0.03781
> scale4 7.882 1.732 0.010001        0.03621
> 
> 2. Quantiles for each variable:
> 
>          2.5%    25%   50%   75% 97.5%
> lm1    4.1876 6.3258 7.460 8.639 11.19
> sill   0.2681 0.6845 1.294 2.898 17.20
> range  0.1143 1.4563 3.518 7.008 18.96
> scale1 4.4400 6.2653 7.338 8.503 11.27
> scale2 4.6810 6.5344 7.594 8.748 11.57
> scale3 5.0229 6.7768 7.851 8.993 12.13
> scale4 4.9102 6.6808 7.732 8.900 11.81
xyplot(BMu1.mcmc)

densityplot(BMu1.mcmc)                             #Densidades

plot(BMu1.mcmc)

# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)

coda::acfplot(BMu1.mcmc)

# gelman.diag(BMu1.mcmc)
# 
# gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
> [[1]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  scale1  scale2  scale3  scale4 
>  0.2156  1.0927  0.4486 -0.1782  0.1399  0.5159  0.3788 
> 
> 
> [[2]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  scale1  scale2  scale3  scale4 
>  0.2156  1.0927  0.4486 -0.1782  0.1399  0.5159  0.3788 
> 
> 
> [[3]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  scale1  scale2  scale3  scale4 
>  0.2156  1.0927  0.4486 -0.1782  0.1399  0.5159  0.3788
#geweke.plot(BMu1.mcmc)
raftery.diag(BMu1.mcmc)
> [[1]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4232  3746         1.130     
>  sill   2        3680  3746         0.982     
>  range  6        6349  3746         1.690     
>  scale1 16       21288 3746         5.680     
>  scale2 12       12594 3746         3.360     
>  scale3 20       22804 3746         6.090     
>  scale4 12       14454 3746         3.860     
> 
> 
> [[2]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4232  3746         1.130     
>  sill   2        3680  3746         0.982     
>  range  6        6349  3746         1.690     
>  scale1 16       21288 3746         5.680     
>  scale2 12       12594 3746         3.360     
>  scale3 20       22804 3746         6.090     
>  scale4 12       14454 3746         3.860     
> 
> 
> [[3]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4232  3746         1.130     
>  sill   2        3680  3746         0.982     
>  range  6        6349  3746         1.690     
>  scale1 16       21288 3746         5.680     
>  scale2 12       12594 3746         3.360     
>  scale3 20       22804 3746         6.090     
>  scale4 12       14454 3746         3.860
# heidel.diag(BMu1.mcmc)

parametro de forma

mc1$chain.shape <- as.data.frame(mc1$chain.shape) %>% 
  mutate(chain = 1)
mc2$chain.shape <- as.data.frame(mc2$chain.shape) %>% 
  mutate(chain = 2)
mc3$chain.shape <- as.data.frame(mc3$chain.shape) %>% 
  mutate(chain = 3)

mc.loc <-  mc1$chain.shape %>% 
  union_all(mc2$chain.shape) %>% union_all(mc3$chain.shape)

post <- posterior_samples(mc.loc, add_chain = T)
mcmc_dens_overlay(post)

post %>% 
  select(lm1, sill, range, shape1, shape2, shape3, shape4) %>% 
  mcmc_acf()

post %>% 
  select(lm1, sill, range, shape1, shape2, shape3, shape4) %>% 
  mcmc_trace()

post %>% 
  select(lm1, sill, range, shape1, shape2, shape3, shape4) %>% 
  mcmc_dens()

post %>% select(lm1) %>% mcmc_trace()

library(coda)

coda::raftery.diag(posterior_samples(post))
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4302  3746          1.15     
>  sill   4        7470  3746          1.99     
>  range  18       24726 3746          6.60     
>  smooth <NA>     <NA>  3746            NA     
>  shape1 25       27610 3746          7.37     
>  shape2 20       22550 3746          6.02     
>  shape3 35       40195 3746         10.70     
>  shape4 40       43312 3746         11.60     
>  chain  69075    69075 3746         18.40
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.shape[,c(-4,-9)]), 
#                             as.mcmc(mc2$chain.shape[,c(-4,-9)]), 
#                             as.mcmc(mc3$chain.shape[,c(-4,-9)])))
# 
# coda::gelman.diag(mcmc.list(as.mcmc(mc1$chain.shape[,1]), 
#                             as.mcmc(mc2$chain.shape[,1]), 
#                             as.mcmc(mc3$chain.shape[,1])))

BMu1.mcmc<-mcmc.list(as.mcmc(mc1$chain.shape[,c(-4,-9)]), 
                     as.mcmc(mc2$chain.shape[,c(-4,-9)]),
                     as.mcmc(mc3$chain.shape[,c(-4,-9)]))

summary(BMu1.mcmc)
> 
> Iterations = 1:10000
> Thinning interval = 1 
> Number of chains = 3 
> Sample size per chain = 10000 
> 
> 1. Empirical mean and standard deviation for each variable,
>    plus standard error of the mean:
> 
>           Mean      SD Naive SE Time-series SE
> lm1     1.4972  0.4314 0.002491       0.004450
> sill    0.7235  1.3091 0.007558       0.016416
> range  12.5102 10.8264 0.062506       0.095027
> shape1  0.4851  0.4474 0.002583       0.012083
> shape2  0.6990  0.3667 0.002117       0.008982
> shape3  0.6816  0.3627 0.002094       0.009493
> shape4  0.6554  0.3448 0.001991       0.008865
> 
> 2. Quantiles for each variable:
> 
>             2.5%     25%    50%     75%  97.5%
> lm1     0.690175 1.18373 1.4942  1.7962  2.347
> sill    0.010189 0.09265 0.3307  0.8542  3.813
> range   0.857001 4.80867 9.5007 16.8548 41.731
> shape1 -0.471204 0.21229 0.5269  0.7836  1.303
> shape2  0.043821 0.44655 0.6809  0.9217  1.466
> shape3  0.029807 0.44552 0.6601  0.8907  1.466
> shape4  0.003297 0.42100 0.6431  0.8797  1.363
xyplot(BMu1.mcmc)

densityplot(BMu1.mcmc)                             #Densidades

plot(BMu1.mcmc)

# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)

coda::acfplot(BMu1.mcmc)

# gelman.diag(BMu1.mcmc)
# 
# gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
> [[1]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  shape1  shape2  shape3  shape4 
>  0.2328  1.2723 -0.8956 -1.2662 -1.4524 -0.9806 -1.0051 
> 
> 
> [[2]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  shape1  shape2  shape3  shape4 
>  0.2328  1.2723 -0.8956 -1.2662 -1.4524 -0.9806 -1.0051 
> 
> 
> [[3]]
> 
> Fraction in 1st window = 0.1
> Fraction in 2nd window = 0.5 
> 
>     lm1    sill   range  shape1  shape2  shape3  shape4 
>  0.2328  1.2723 -0.8956 -1.2662 -1.4524 -0.9806 -1.0051
#geweke.plot(BMu1.mcmc)
raftery.diag(BMu1.mcmc)
> [[1]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4302  3746          1.15     
>  sill   3        4232  3746          1.13     
>  range  8        10110 3746          2.70     
>  shape1 25       27615 3746          7.37     
>  shape2 15       15468 3746          4.13     
>  shape3 32       38800 3746         10.40     
>  shape4 18       17121 3746          4.57     
> 
> 
> [[2]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4302  3746          1.15     
>  sill   3        4232  3746          1.13     
>  range  8        10110 3746          2.70     
>  shape1 25       27615 3746          7.37     
>  shape2 15       15468 3746          4.13     
>  shape3 32       38800 3746         10.40     
>  shape4 18       17121 3746          4.57     
> 
> 
> [[3]]
> 
> Quantile (q) = 0.025
> Accuracy (r) = +/- 0.005
> Probability (s) = 0.95 
>                                               
>         Burn-in  Total Lower bound  Dependence
>         (M)      (N)   (Nmin)       factor (I)
>  lm1    3        4302  3746          1.15     
>  sill   3        4232  3746          1.13     
>  range  8        10110 3746          2.70     
>  shape1 25       27615 3746          7.37     
>  shape2 15       15468 3746          4.13     
>  shape3 32       38800 3746         10.40     
>  shape4 18       17121 3746          4.57
# heidel.diag(BMu1.mcmc)
DIC(mc)

x.grid <- seq(-95, -90, length = 20)
y.grid <- seq(14, 19, length = 20)
# map.latent(mc, x.grid, y.grid, param = "loc")
# map.latent(mc, x.grid, y.grid, param = "loc", plot.contour = F)
# map.latent(mc, x.grid, y.grid, param = "loc", plot.contour = T, show.data = F)
# map.latent(mc, x.grid, y.grid, param = "loc", plot.contour = T, show.data = T)

# head(mc$chain.loc[,6])
# head(mc$chain.scale)
# head(mc$chain.shape)
# head(mc$loc.dsgn.mat)
# head(mc$scale.dsgn.mat)
# head(mc$Dbar)
# summary(mc)
library(lattice)
library(coda)
# autocorr.plot(as.mcmc(mc$chain.loc[,1]))
# coda::gelman.diag(as.mcmc(mc$chain.loc[,1]))
BMu1.mcmc<-mcmc.list(as.mcmc(mc$chain.shape[,5]), 
                     as.mcmc(mc$chain.shape[,6]),
                     as.mcmc(mc$chain.shape[,7]),
                     as.mcmc(mc$chain.shape[,8]))

summary(BMu1.mcmc)
xyplot(BMu1.mcmc)
densityplot(BMu1.mcmc)                             #Densidades
plot(BMu1.mcmc)
# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)
coda::acfplot(BMu1.mcmc)

gelman.diag(BMu1.mcmc)

gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
#geweke.plot(BMu1.mcmc)
raftery.diag(BMu1.mcmc)
# heidel.diag(BMu1.mcmc)


library(lattice)
library(coda)
BMu1.mcmc<-mcmc.list(as.mcmc(mc$chain.loc[,5]),
                     as.mcmc(mc$chain.loc[,6]),
                     as.mcmc(mc$chain.loc[,7]),
                     as.mcmc(mc$chain.loc[,8]))

summary(BMu1.mcmc)
xyplot(BMu1.mcmc)
densityplot(BMu1.mcmc)                             #Densidades
plot(BMu1.mcmc)
# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)
coda::acfplot(BMu1.mcmc)

gelman.diag(BMu1.mcmc)

gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
#geweke.plot(BMu1.mcmc)
# raftery.diag(BMu1.mcmc)
# heidel.diag(BMu1.mcmc)


BMu1.mcmc<-mcmc.list(as.mcmc(mc$chain.scale[,6]),
                     as.mcmc(mc$chain.scale[,7]),
                     as.mcmc(mc$chain.scale[,8]),
                     as.mcmc(mc$chain.scale[,9]),
                     as.mcmc(mc$chain.scale[,10]))

summary(BMu1.mcmc)
xyplot(BMu1.mcmc)
densityplot(BMu1.mcmc)                             #Densidades
plot(BMu1.mcmc)
# layout(matrix(1:12, 3,4));  

traceplot(BMu1.mcmc)

#Grafica de autocorrelacion
autocorr.plot(BMu1.mcmc, auto.layout = TRUE, ask =F)
coda::acfplot(BMu1.mcmc)

gelman.diag(BMu1.mcmc)

gelman.plot(BMu1.mcmc)

geweke.diag(BMu1.mcmc)
#geweke.plot(BMu1.mcmc)
raftery.diag(BMu1.mcmc)
# heidel.diag(BMu1.mcmc)
LS0tDQp0aXRsZTogIkExMCINCmF1dGhvcjogIkRhdmlkIEFsZWphbmRybyBPenVuYSBTYW50aWFnbyINCmRhdGU6ICIzLzYvMjAyMSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICB0b2M6IHllcw0KICAgICMgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQotLS0NCg0KPHN0eWxlPg0KYm9keSB7DQp0ZXh0LWFsaWduOiBqdXN0aWZ5fQ0KPC9zdHlsZT4NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgY2xhc3Muc291cmNlID0gJ2ZvbGQtaGlkZSd9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudD0iPiIsDQogICNlY2hvPUZBTFNFLCAgIyBQYXJhIG1vc3RyYXIgZWwgY29kaWdvIFIgZW4gbGEgc2FsaWRhDQogICMgcmVzdWx0cyA9ICdhc2lzJywNCiAgd2FybmluZyA9IEZBTFNFLA0KICBtZXNzYWdlID0gRkFMU0UpDQoNCmBgYA0KDQojIERlc2NyaXBjacOzbiBkZSBsYSBiYXNlIGRlIGRhdG9zDQoNCkVsIGNvbmp1bnRvIGRlIGRhdG9zIGNvbnRpZW5lIHViaWNhY2lvbmVzIGRlIGVzdGFjaW9uZXMgbWV0ZW9yb2xvZ2ljYXMgdWJpY2FkYXMgZW4gZWwgcGFpcyBkZSBNZXhpY28sIGFsZ3Vub3MgZGV0YWxsZXMgc29icmUgbGFzIGVzdGFjaW9uZXMgbWV0ZW9yb2xvZ2ljYXMgc29uIGxvcyBzaWd1ZW50ZXM6DQoNCg0KKiDCv0N1YW50YXMgZXN0YWNpb25lcyB0ZW5lbW9zPw0KDQplbCBjb25qdW50byBkZSBkYXRvcyBjb250aWVuZSA0OTMgYXJjaGl2b3MgZGUgZXhjZWwsIGRvbmRlIGVzdG9zIHNlIGRpdmlkZW4gZW4gZXN0YWNpb25lcyBwYXJhIGxvcyBlc3RhZG9zIGNvcnJlc3BvbmRpZW50ZXMgcXVlIHNvbiBDaGlhcGFzICg1KSwgVGFiYXNjbyAoMSkgeSBWZXJhY3J1eiAoNikgY29uIDUsIDEgeSA2IGVzdGFjaW9uZXMgbWV0ZW9yb2xvZ2ljYXMgZW4gY2FkYSBlc3RhZG8gY29ycmVzcG9uZGllbnRlbWVudGUsIGVudG9uY2VzIGxvcyA0OTMgYXJjaGl2b3MgdmFuIHZhcmlhbmRvIGNvbmZvcm1lIGFsIHRpZW1wbywgYWxndW5vcyBjb25mb3JtZSBhIGHDsW9zLCBvdHJvcyBjb25mb3JtZSBhIG1lc2VzLCBvdHJvcyBjb25mb3JtZSBhIGNvbmp1bnRvIGRlIG1lc2VzIGVuIGxhcyAxMiBlc3RhY2lvbmVzIG1ldGVvcm9sb2dpY2FzIG11ZXN0cmVhZGFzLCBwZXJvIHRvZG9zIHZhcmlhbiBjb25mb3JtZSBhIGRpYXMgcmVzcGVjdGl2YW1lbnRlLiBBIGNvbnRpbnVhY2nDs24gc2UgbXVlc3RyYW4gbG9zIG5vbWJyZXMgZGUgbGFzIGVzdGFjaW9uZXMgcXVlIGNvbnRpZW5lbiBsb3MgZXN0YWRvcyBjb3JyZXNwb25kaWVudGVzOg0KDQpWZXJhY3J1eiAoNiBlc3RhY2lvbmVzKQ0KDQotICsgQWx2YXJhZG8gDQotICsgQ29hdHphY29hbGNvcw0KLSArIE9yaXphYmENCi0gKyBUdXhwYW4gDQotICsgVmVyYWNydXoNCi0gKyBYYWxhcGENCg0KQ2hpYXBhcyAoNSBlc3RhY2lvbmVzKQ0KDQoNCi0gKyBBcnJpYWdhIA0KLSArIENvbWl0YW4gDQotICsgU2FuIENyaXN0b2JhbCBkZSBsYXMgQ2FzYXMNCi0gKyBUYXBhY2h1bGENCi0gKyBUdXh0bGEgR3V0aWVycmV6DQoNCg0KVGFiYXNjbyAoMSBlc3RhY2nDs24pDQoNCi0gKyBWaWxsYWhlcm1vc2ENCg0KDQpBc2kgdGFtYmllbiBleGlzdGVuIG11Y2hvcyBhcmNoaXZvcyBkZSBleGNlbCB2YWNpb3MsIGVudHJlIGVsbG9zIHNlIGVuY3VlbnRyYW4uDQoNCiMjIGRlc2NyaXBjacOzbiBkZSB2YXJpYWJsZXMNCg0KbGFzIHZhcmlhYmxlcyBxdWUgc2UgaW5jbHV5ZW4gZW4gbG9zIGNvbmp1bnRvcyBkZSBkYXRvcyBzb24gbG9zIHNpZ3VpZW50ZXM6DQoNCisgU1IgPSAgUmFkaWFjacOzbiBzb2xhcg0KDQorIFJhaW4gPSBMbHV2aWEgKHRvbWFkYSBlbiBlbCB0aWVtcG8gZW4gaG9yYXMpDQoNCisgRFAgPSBUZW1wZXJhdHVyYSBhbCBwdW50byBkZSByb2PDrW8uDQoNCisgUkggPSBIdW1lZGFkIHJlbGF0aXZhDQoNCisgVFMgPSBUZW1wZXJhdHVyYSBhIDEwIGNtIGRlIGxhIHN1cGVyZmljaWUNCg0KKyBBVEMgPSBBaXIgdHJhZmZpYyBjb250cm9sICh0cmFmaWNvIGRlIGNvbnRyb2wgYWVyZW8pDQoNCisgV1MgPSAgdmVsb2NpZGFkIGRlbCB2aWVudG8NCg0KKyBXRCA9IERpcmVjY2nDs24gZGVsIHZpZW50bw0KDQorIFFGRiA9IFFGRiBlcyB1biBjw7NkaWdvIGFlcm9uw6F1dGljby4gRXMgbGEgcHJlc2nDs24gTVNMKE1lYW4gU2VhIExldmVsLCBhbHRpdHVkIHRvbWFuZG8gY29tbyByZWZlcmVuY2lhIGVsIG5pdmVsIG1lZGlvIGRlbCBtYXIpIGRlcml2YWRhIGRlIGxhcyBjb25kaWNpb25lcyBkZSBsYSAgZXN0YWNpw7NuIG1ldGVvcm9sw7NnaWNhIGxvY2FsLiBEZSBhY3VlcmRvIGNvbiBsYSAgcHLDoWN0aWNhIG1ldGVvcm9sw7NnaWNhIFFGRiBlcyBsYSBwcmVzacOzbiBtZWRpYSBhbCBuaXZlbCBkZWwgbWFyLCBkZXJpdmFkYSAgdGVuaWVuZG8gZW4gY3VlbnRhIGxhcyBjb25kaWNpb25lcyBkZSB0ZW1wZXJhdHVyYSByZWFsZXMuDQoNCisgQlAgPSBMYSBwcmVzacOzbiBhdG1vc2bDqXJpY2EsIHRhbWJpw6luIGNvbm9jaWRhIGNvbW8gIHByZXNpw7NuIGJhcm9tw6l0cmljYSAoZGVzcHXDqXMgZGVsIGJhcsOzbWV0cm8pLCBlcyBsYSBwcmVzacOzbiBkZW50cm8gZGUgbGEgYXRtw7NzZmVyYSBkZSBsYSBUaWVycmEuDQoNCiMjIERlc2NyaXBjacOzbiBkZSBsYXMgZXN0YWNpb25lcyBtZXRlb3JvbG9naWNhcw0KDQpfX0Rlc2NyaXBjacOzbiBkZSB1bmEgRXN0YWNpw7NuIFNpbsOzcHRpY2EgTWV0ZW9yb2zDs2dpY2EgLSBFU0lNRV9fDQoNClVuYSBFc3RhY2nDs24gU2luw7NwdGljYSBNZXRlb3JvbMOzZ2ljYSBlcyB1biBjb25qdW50byBkZSBkaXNwb3NpdGl2b3MgZWzDqWN0cmljb3MgcXVlIHJlYWxpemFuIG1lZGljaW9uZXMgZGUgbGFzIHZhcmlhYmxlcyBtZXRlb3JvbMOzZ2ljYXMgZGUgbWFuZXJhIGF1dG9tw6F0aWNhLiBHZW5lcmFuIHVuYSBiYXNlIGRlIGRhdG9zIHkgZ2VuZXJhbiB1biBtZW5zYWplIHNpbsOzcHRpY28gY2FkYSB0cmVzIGhvcmFzLg0KDQpMb3MgbWVuc2FqZXMgc2luw7NwdGljb3Mgc29uIHJlcG9ydGVzIHF1ZSBzZSBnZW5lcmFuIHNpbXVsdMOhbmVhbWVudGUgZW4gdG9kb3MgbG9zIG9ic2VydmF0b3Jpb3MgY2FkYSB0cmVzIGhvcmFzIHkgcHJlc2VudGFuIGluZm9ybWFjacOzbiBtZXRlb3JvbMOzZ2ljYSBkZSB0aWVtcG8gcHJlc2VudGUgeSBwYXNhZG8gZGUgbWFuZXJhIGNvZGlmaWNhZGEuIExvcyBtZW5zYWplcyBzaW7Ds3B0aWNvcyBzZSByaWdlbiBwb3IgZWwgVGllbXBvIFVuaXZlcnNhbCBDb29yZGluYWRvIChVVEMpLg0KDQpOb3RhOiBFbCDDoXJlYSByZXByZXNlbnRhdGl2YSBkZSBsYXMgZXN0YWNpb25lcyBlcyBkZSA1IGttIGRlIHJhZGlvIGFwcm94aW1hZGFtZW50ZSwgZW4gdGVycmVubyBwbGFubywgZXhjZXB0byBlbiB0ZXJyZW5vIG1vbnRhw7Fvc28uIChSZWZlcmVuY2lhIE9NTSBuw7ptZXJvIDEwMCB5IDE2OCkNCg0KYGBge3IsIGNhY2hlPVRSVUUsIGZpZy5jYXA9IkVzdGFjacOzbiBFU0lNRSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZjAuanBnIiwgZHBpID0gMTApDQpgYGANCg0KDQojIyBkZXNjcmlwY2nDs24gZGVsIGVzdHVkaW8NCg0KTXV5IGJpZW4sIHByaW5jaXBhbG1lbnRlIGVzdGFtb3MgaW50ZXJlc2Fkb3MgZW4gbWVkaXIgZW4gcHJpbWVyIGx1Z2FyIGxhIGxsdXZpYSAocmFpbikgbWVkaWFudGUgdmFsb3JlcyBleHRyZW1vcyB5IGVsIHVzbyBkZSBnZW9lc3RhZGlzdGljYSwgcGVybyBwYXJhIGVsbG8gZGViZW1vcyBjb25zaWRlcmFyIGxhIGxsdXZpYSBvIG1lam9yIGNvbm9jaWRhIGNvbW8gcHJlY2lwaXRhY2lvbmVzIGV4dHJlbWFzLg0KDQpDb25mb3JtZSBhIFJvYmVydCBNb25qbywgV2lraXBlZGlhIHkgZGl2ZXJzb3MgYXV0b2VyZXMsIHBvZGVtb3MgY2F0ZWdvcml6YXIgbGEgcHJlY2lwaXRhY2nDs24gY29uZm9ybWUgYSBlc3R1ZGlvcyBkZSBsYSAgQWdlbmNpYSBFc3RhdGFsIGRlIE1ldGVvcm9sb2fDrWEsIGxvcyBjdWFsZXMgaW5kaWNhbiBxdWUgDQoNCj4gU2kgcXVlcmVtb3MgZXN0dWRpYXIgZWwgY29tcG9ydGFtaWVudG8gZGUgbGEgbGx1dmlhIGVuIGVsIHRpZW1wbywgZGViZW1vcyBmaWphcm5vcyBlbiBjw7NtbyBzZSBkaXN0cmlidXllIGxhIGludGVuc2lkYWQgYSBsbyBsYXJnbyBkZWwgbWlzbW8uIFVzdWFsbWVudGUgc2UgdXNhIGVsIGNvbmNlcHRvIGRlIGludGVuc2lkYWQgcGFyYSByZWZlcmlybm9zIGEgdmFsb3JlcyBtZWRpbywgZXMgZGVjaXIsIGEgdW5hIGNpZXJ0YSBjYW50aWRhZCBkZSBwcmVjaXBpdGFjacOzbiByZWdpc3RyYWRhIGVuIHVuIHRpZW1wbyBkZXRlcm1pbmFkbzogdW5hIGhvcmEsIHVuIG1pbnV0bywgbyBiaWVuIGVsIHBhc28gZW50cmUgZG9zIG9zY2lsYWNpb25lcyBkZSB0aWVtcG8gZGUgdW5hIGVzdGFjacOzbiBhdXRvbcOhdGljYS4NCg0KVGFibGEgMS4gQ2xhc2lmaWNhY2nDs24gZGUgbGEgbGx1dmlhIHNlZ8O6biBsYSBpbnRlbnNpZGFkIG1lZGlhIGVuIHVuYSBob3JhLiBBZ2VuY2lhIEVzdGF0YWwgZGUNCk1ldGVvcm9sb2fDrWEuIA0KDQpgYGB7ciwgY2FjaGU9VFJVRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmMS5wbmciLCBkcGkgPSAxMCkNCmBgYA0KDQpNdXkgYmllbiwgZW50b25jZXMgcGFyYSBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zIHRlbmVtb3MgbGFzIG1lZGljaW9uZXMgcXVlIHZhbiBkZXNkZSAxMCBtaW4sIDEgaG9yYSwgMyBob3JhcywgNiBob3JhcyB5IDI0IGhvcmFzLCBlbnRvbmNlcyBwYXJhIHRvbWFyIGVuIGN1ZW50YSBsYSBpbmZvcm1hY2nDs24gYW50ZXJpb3Igbm9zIHZhbW9zIGEgY2VudHJhciBlbiBsYXMgbWVkaWNpb25lcyBxdWUgc2UgcmVhbGl6YXJvbiBwb3IgaG9yYS4gDQoNCkEgY29udGludWFjacOzbiBjb21vIGVqZW1wbG8gdmFtb3MgYSBzZWxlY2Npb25hciBlbCBjb25qdW50byBkZSBkYXRvcyBkZSBDaGlhcGFzIChlc3RvIGRlYmlkbyBhIHF1ZSB0aWVuZSA1IGVzdGFjaW9uZXMgcGVybyB0YW1iaWVuIHB1ZGltb3Mgc2VsZWNjaW9uYXIgVmVyYWNydXopIHkgY29uZm9ybWUgYSBsYSBtZXRvZG9sb2dpYSBkZSBBLiBDLiBEYXZpc29uLCBTLiBBLiBQYWRvYW4gYW5kIE0uIFJpYmF0ZXQsIGNvbnNpZGVyYXJlIGxhIHByZWNpcGl0YWNpw7NuIG1heGltYSBkaWFyaWEgZGUgbG9zIG1lc2VzIGRlIGp1bmlvIGEgb2N0dWJyZSBwYXJhIGxvcyBhw7FvcyAyMDE4LCAyMDE5IHkgMjAyMCwgZW4gNSBlc3RhY2lvbmVzIG1ldGVvcm9sw7NnaWNhcyBlbiBsYSByZWdpw7NuIGRlIENoaWFwYXMsIHByb3BvcmNpb25hZGEgcG9yIGVsIHNlcnZpY2lvIG1ldGVvcm9sw7NnaWNvIG5hY2lvbmFsLiBMYSBlbGVjY2nDs24gZGUgZXN0b3MgbWVzZXMgZXMgZGVkaWJvIGEgcXVlICBlc3RlIGNvbmp1bnRvIGRlIG1lc2VzIHNlIGVuY3VlbnRyYW4gZGVudHJvIGRlbCB2ZXJhbm8sIGFsZ28gcXVlIGVzIGltcG9ydGFudGUgZGVzdGFjYXIgZXMgZWwgY29tZW50YXJpbyBkZSBHZXJ5LWNvIFByYW5rc3RlciwgKDIwMTApLCBlbCBjdWFsIGluZGljYSBxdWUgbGFzIHByZWNpcGl0YWNpb25lcyBzb24gbWF5b3JlcyBlcyBlc2EgdGVtcG9yYWRhLCBzaW4gZW1iYXJnbyBlbCBWZXJhbm86IGluaWNpYSBlbCAyMSBkZSBqdW5pbyB5IGZpbmFsaXphIGVsIDIyIGRlIHNlcHRpZW1icmUuIFBvciBsbyB0YW50byBwYXJhIGVsIGFuYWxpc2lzIHNlIGNvbnNpZGVyYW4gbG9zIG1lc2VzIGRlIGp1bmlvIGEgb2N0dWJyZS4NCg0KPCEtLSBsYSBtZXRvZG9sb2dpYSBkZSBBLiBDLiBEYXZpc29uLCBTLiBBLiBQYWRvYW4gYW5kIE0uIFJpYmF0ZXQgdXRpbGl6YW1vcyBsYSBwcmVjaXBpdGFjacOzbiBtw6F4aW1hIGRpYXJpYSBkZSB2ZXJhbm8gcGFyYSBsb3MgYcOxb3MgMjAxOC0yMDIwIGVuIDUgZXN0YWNpb25lcyBtZXRlb3JvbMOzZ2ljYXMgZW4gbGEgcmVnacOzbiBkZSBDaGlhcGFzLCBwcm9wb3JjaW9uYWRhIHBvciBlbCBzZXJ2aWNpbyBtZXRlb3JvbMOzZ2ljbyBuYWNpb25hbC4gLS0+DQoNCkNvbW8gYmllbiBzYWJlbW9zLCBDaGlhcGFzIHRpZW5lIDUgZXN0YWNpb25lcywgZW4gZG9uZGUgZW4gbnVlc3RybyBjb25qdW50byBkZSBkYXRvcyBzZSBlbmN1ZW50cmEgbGEgc2lndWllbnRlIGluZm9ybWFjacOzbi4NCg0KDQo8IS0tIC0gQXJyaWFnYSA6IC0tPg0KDQo8IS0tICAgKyAyMDA2OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAwNzogZW5lLWp1biAtLT4NCjwhLS0gICArIDIwMDk6IG1heS1kaWMgLS0+DQo8IS0tICAgKyAyMDEwOiAqKm1hcioqIC0tPg0KPCEtLSAgICsgMjAxMTogc2VwLWRpYyAtLT4NCjwhLS0gICArIDIwMTI6IGVuZS1ub3YgLS0+DQo8IS0tICAgKyAyMDE0OiBmZWItbWF5IC0tPg0KPCEtLSAgICsgMjAxODogZW5lLWp1biAtLT4NCjwhLS0gICArIDIwMTk6ICoqc2VwLCBvY3QsIG5vdioqIC0tPg0KPCEtLSAgICsgMjAyMDogKiphZ28qKiAtLT4NCg0KPCEtLSAtIENvbWl0YW4gIC0tPg0KDQo8IS0tICAgKyAyMDEzOiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxNDogZW5lLWRpYyAtLT4NCjwhLS0gICArIDIwMTU6IGVuZS1kaWMgLS0+DQo8IS0tICAgKyAyMDE2OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxNzogZW5lLWRpYyAtLT4NCjwhLS0gICArIDIwMTg6IGVuZS1qdW4sIGp1bC1kaWMgLS0+DQo8IS0tICAgKyAyMDE5OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAyMDogZW5lLWRpYyAtLT4NCg0KPCEtLSAtIFNhbiBDcmlzdG9iYWwgZGUgbGFzIENhc2FzIC0tPg0KDQo8IS0tICAgKyAyMDEzOiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxNDogZW5lLWRpYyAtLT4NCjwhLS0gICArIDIwMTU6IGVuZS1kaWMgLS0+DQo8IS0tICAgKyAyMDE2OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxNzogZW5lLWRpYyAtLT4NCjwhLS0gICArIDIwMTg6IGVuZS1qdW4sIGp1bC1kaWMgLS0+DQo8IS0tICAgKyAyMDE5OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAyMDogKipvY3QsIG5vdiwgZGljKiogLS0+DQoNCjwhLS0gLSBUYXBhY2h1bGEgLS0+DQoNCjwhLS0gICArIDIwMTE6ICpmZWIqIC0tPg0KPCEtLSAgICsgMjAxMjogZW5lLW9jdCAtLT4NCjwhLS0gICArIDIwMTM6IGVuZS1kaWMgLS0+DQo8IS0tICAgKyAyMDE0OiAqKm9jdCwgbm92KiogLS0+DQo8IS0tICAgKyAyMDE1OiAqKmFiciwgbWF5LCBvY3QsIG5vdiwgZGljKiogLS0+DQo8IS0tICAgKyAyMDE3OiBub3YtZGljIC0tPg0KPCEtLSAgICsgMjAxODogZW5lLWp1biwganVsLWRpYyAgLS0+DQo8IS0tICAgKyAyMDE5OiAqKmZlYioqIC0tPg0KPCEtLSAgICsgMjAyMDogZW5lLWRpYyAtLT4NCg0KPCEtLSAtIFR1eHRsYSBHdXRpZXJyZXogLS0+DQoNCjwhLS0gICArIDIwMTM6IGVuZS1kaWMgLS0+DQo8IS0tICAgKyAyMDE0OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxNTogZW5lLWRpYyAtLT4NCjwhLS0gICArIDIwMTY6IGVuZS1kaWMgLS0+DQo8IS0tICAgKyAyMDE3OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAxODogZW5lLWp1biwganVsLWRpYyAgLS0+DQo8IS0tICAgKyAyMDE5OiBlbmUtZGljIC0tPg0KPCEtLSAgICsgMjAyMDogZW5lLWRpYyAtLT4NCg0KDQotIEFycmlhZ2EgOg0KDQogICsgMjAwNjogZW5lLWRpYw0KICArIDIwMDc6IGVuZS1qdW4NCiAgKyAyMDA5OiBtYXktZGljDQogICsgMjAxMDogKiptYXIqKg0KICArIDIwMTE6IHNlcC1kaWMNCiAgKyAyMDEyOiBlbmUtbm92DQogICsgMjAxNDogZmViLW1heQ0KICArIDIwMTg6IGVuZS1qdW4NCiAgKyAyMDE5OiBlbmUtZGljDQogICsgMjAyMDogZW5lLWRpYw0KICANCi0gQ29taXRhbiANCg0KICArIDIwMTM6IGVuZS1kaWMNCiAgKyAyMDE0OiBlbmUtZGljDQogICsgMjAxNTogZW5lLWRpYw0KICArIDIwMTY6IGVuZS1kaWMNCiAgKyAyMDE3OiBlbmUtZGljDQogICsgMjAxODogZW5lLWp1biwganVsLWRpYw0KICArIDIwMTk6IGVuZS1kaWMNCiAgKyAyMDIwOiBlbmUtZGljDQogIA0KLSBTYW4gQ3Jpc3RvYmFsIGRlIGxhcyBDYXNhcw0KDQogICsgMjAxMzogZW5lLWRpYw0KICArIDIwMTQ6IGVuZS1kaWMNCiAgKyAyMDE1OiBlbmUtZGljDQogICsgMjAxNjogZW5lLWRpYw0KICArIDIwMTc6IGVuZS1kaWMNCiAgKyAyMDE4OiBlbmUtanVuLCBqdWwtZGljDQogICsgMjAxOTogZW5lLWRpYw0KICArIDIwMjA6IGVuZS1kaWMNCiAgDQotIFRhcGFjaHVsYQ0KDQogICsgMjAxMTogKmZlYioNCiAgKyAyMDEyOiBlbmUtb2N0DQogICsgMjAxMzogZW5lLWRpYw0KICArIDIwMTQ6ICoqb2N0LCBub3YqKg0KICArIDIwMTU6ICoqYWJyLCBtYXksIG9jdCwgbm92LCBkaWMqKg0KICArIDIwMTc6IG5vdi1kaWMNCiAgKyAyMDE4OiBlbmUtanVuLCBqdWwtZGljIA0KICArIDIwMTk6ICoqZmViKioNCiAgKyAyMDIwOiBlbmUtZGljDQogIA0KLSBUdXh0bGEgR3V0aWVycmV6DQoNCiAgKyAyMDEzOiBlbmUtZGljDQogICsgMjAxNDogZW5lLWRpYw0KICArIDIwMTU6IGVuZS1kaWMNCiAgKyAyMDE2OiBlbmUtZGljDQogICsgMjAxNzogZW5lLWRpYw0KICArIDIwMTg6IGVuZS1qdW4sIGp1bC1kaWMgDQogICsgMjAxOTogZW5lLWRpYw0KICArIDIwMjA6IGVuZS1kaWMNCg0KDQojIExpbXBpZXphIGRlIGxhIGJhc2UgZGUgZGF0b3MNCg0KIyMgY2FyZ2Ftb3MgbG9zIGRhdG9zDQoNCg0KYGBge3IsIGNhY2hlPVRSVUUsIGV2YWwgPSBGfQ0KYXJyaWFnYTIwMTggPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL0FycmlhZ2EgMjAxOC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQphcnJpYWdhMjAxOSA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvQXJyaWFnYSAyMDE5LmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCmFycmlhZ2EyMDIwIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9EYXZpZC9PbmVEcml2ZS9Eb2N1bWVudG9zL01NQS9zZW1pbmFyaW8gZGUgdGVzaXMgMi9hdmFuY2VzIHNlbWluYXJpby9kYXRvcy9iYXNlL0NoaWFwYXMgNS9zdW1tZXIvZGF0YS9BcnJpYWdhIDIwMjAuY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KIyBUaHUgTWF5IDIwIDAyOjAyOjM4IDIwMjEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCmNvbWl0YW4yMDE4IDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9EYXZpZC9PbmVEcml2ZS9Eb2N1bWVudG9zL01NQS9zZW1pbmFyaW8gZGUgdGVzaXMgMi9hdmFuY2VzIHNlbWluYXJpby9kYXRvcy9iYXNlL0NoaWFwYXMgNS9zdW1tZXIvZGF0YS9Db21pdGFuIDIwMTguY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KY29taXRhbjIwMTkgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL0NvbWl0YW4gMjAxOS5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQpjb21pdGFuMjAyMCA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvQ29taXRhbiAyMDIwLmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCiMgVGh1IE1heSAyMCAwMjowMzowMyAyMDIxIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpzY2RsYzIwMTggPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL3NjZGxjIDIwMTguY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0Kc2NkbGMyMDE5IDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9EYXZpZC9PbmVEcml2ZS9Eb2N1bWVudG9zL01NQS9zZW1pbmFyaW8gZGUgdGVzaXMgMi9hdmFuY2VzIHNlbWluYXJpby9kYXRvcy9iYXNlL0NoaWFwYXMgNS9zdW1tZXIvZGF0YS9zY2RsYyAyMDE5LmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCnNjZGxjMjAyMCA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvc2NkbGMgMjAyMC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQojIFRodSBNYXkgMjAgMDI6MDc6MTggMjAyMSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KdGFwYWNodWxhMjAxOCA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvVGFwYWNodWxhIDIwMTguY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KdGFwYWNodWxhMjAxOSA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvVGFwYWNodWxhIDIwMTkuY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KdGFwYWNodWxhMjAyMCA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvVGFwYWNodWxhIDIwMjAuY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KIyBUaHUgTWF5IDIwIDAyOjA4OjQ0IDIwMjEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCnR1eHRsYTIwMTggPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL1R1eHRsYSAyMDE4LmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCnR1eHRsYTIwMTkgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL1R1eHRsYSAyMDE5LmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCnR1eHRsYTIwMjAgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL1R1eHRsYSAyMDIwLmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCmBgYA0KDQojIyBmaWx0cmFtb3MNCg0KYSBjb250aW51YWNpw7NuIHNlIGZpbHRyYSBwb3IgZGlhIHkgbWVzIHJlc3BlY3RpdmFtZW50ZSB0b21hbmRvIGxhIGxsdXZpYSBhY3VtdWxhZGEgcG9yIGRpYSwgdGVuZ28gZW4gY3VhbnRhIHF1ZSBzZSBlc3RhIGZpbHRyYW5kbyBwYXJhIG1lc2VzIGNvbiAzMCBkaWFzIHkgbWVzZXMgY29uIDMxIGRpYXMsIGRvbmRlIA0KDQorIG1lc2VzIGNvbiAzMCBkw61hcyBzb24gOiBKdW5pbywgU2VwdGllbWJyZS4NCg0KKyBNZXNlcyBjb24gMzEgZMOtYXM6ICBKdWxpbywgQWdvc3RvLCBPY3R1YnJlLg0KDQpFbCBwcm9jZWRpbWllbnRvIGVzIGVsIHNpZ3VpZW50ZToNCg0KMS4gQ3JlYW1vcyB1biBkYXRhIGZyYW1lIHZhY2lvIGRvbmRlIGluY2x1aW1vcyBudWVzdHJhIG51ZXZhIGNvbHVtbmEgKGN1bV9yYWluKS4NCg0KMi4gRWplY3V0YW1vcyB1biBjaWNsbyBwYXJhIGxvcyBtZXNlcyBkZSAzMCBkaWFzDQoNCjMuIGZpbHRyYW1vcyBsYSBiYXNlIGRlIGRhdG9zIHBvciBtZXMgeSBkaWEsIGNyZWFtb3MgbGEgbnVldmEgdmFyaWFibGUgZGUgbGx1dmlhIGFjdW11bGFkYSB5IHNlbGVjY2lvbmFtb3MgZWwgdWx0aW1vIHZhbG9yIGFjdW11bGFkbyBkZSBsYSBsbHV2aWEgcGFyYSBlc2UgZGlhIHJlc3BlY3RpdmFtZW50ZS4NCg0KNC4gc2kgZWwgbnVtZXJvIGRlIGZpbGFzID0gMCAoZXN0byBkZWJpZG8gcG9ycXVlIGFsZ3Vub3MgbWVzZXMgbm8gY29udGllbmVuIG1lZGljaW9uZXMgZW4gZMOtYXMgZXNwZWNpZmljb3MsIGxvIGN1YWwgbm9zIGxsZXZhIGEgbm8gdGVuZXIgbGx1dmlhIGFjdW11bGFkYSBlbiBlc2UgZGlhKSwgYcOxYWRpbW9zIHVuYSBudWV2YSBmaWxhIGNvbiBtZWRpY2lvbiBjZXJvIHBhcmEgZXNlIGRpYSByZXNwZWN0aXZhbWVudGUuDQoNCjUuIGNyZWFtb3MgbnVlc3RybyBkYXRhIGZyYW1lDQoNCiMjIyBBcnJpYWdhDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCiMgYXJyaWFnYSAyMDE4IHNlbGVjY2lvbmFuZG8gZWwgbWF4aW1vIGFjdW11bGFkbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kbi5hcnJpYWdhMjAxOC4zMCA8LSAoYXJyaWFnYTIwMTggJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIGFycmlhZ2EyMDE4ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIkFycmlhZ2EiLCBqLCBpLCAyMDE4LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4uYXJyaWFnYTIwMTguMzAgPC0gcmJpbmQobi5hcnJpYWdhMjAxOC4zMCxhKQ0KICAgICAgICB9DQp9DQoNCm4uYXJyaWFnYTIwMTguMzEgPC0gKGFycmlhZ2EyMDE4ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gYXJyaWFnYTIwMTggJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiQXJyaWFnYSIsIGosIGksIDIwMTgsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5hcnJpYWdhMjAxOC4zMSA8LSByYmluZChuLmFycmlhZ2EyMDE4LjMxLGEpDQogICAgICAgIH0NCn0NCg0Kbl9hcnJpYWdhMjAxOCA8LSBuLmFycmlhZ2EyMDE4LjMwICU+JSANCiAgdW5pb25fYWxsKG4uYXJyaWFnYTIwMTguMzEpDQoNCg0KIyBhcnJpYWdhIDIwMTkgc2VsZWNjaW9uYW5kbyBlbCBtYXhpbW8gYWN1bXVsYWRvIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpuLmFycmlhZ2EyMDE5LjMwIDwtIChhcnJpYWdhMjAxOSAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg2LCA5KSkgew0KICAgIGZvciAoaiBpbiAxOjMwKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gYXJyaWFnYTIwMTkgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiQXJyaWFnYSIsIGosIGksIDIwMTksIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5hcnJpYWdhMjAxOS4zMCA8LSByYmluZChuLmFycmlhZ2EyMDE5LjMwLGEpDQogICAgICAgIH0NCn0NCg0Kbi5hcnJpYWdhMjAxOS4zMSA8LSAoYXJyaWFnYTIwMTkgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNywgOCwgMTApKSB7DQogICAgZm9yIChqIGluIDE6MzEpIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSBhcnJpYWdhMjAxOSAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJBcnJpYWdhIiwgaiwgaSwgMjAxOSwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLmFycmlhZ2EyMDE5LjMxIDwtIHJiaW5kKG4uYXJyaWFnYTIwMTkuMzEsYSkNCiAgICAgICAgfQ0KfQ0KDQpuX2FycmlhZ2EyMDE5IDwtIG4uYXJyaWFnYTIwMTkuMzAgJT4lIA0KICB1bmlvbl9hbGwobi5hcnJpYWdhMjAxOS4zMSkNCg0KIyBhcnJpYWdhIDIwMjAgc2VsZWNjaW9uYW5kbyBlbCBtYXhpbW8gYWN1bXVsYWRvIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpuLmFycmlhZ2EyMDIwLjMwIDwtIChhcnJpYWdhMjAyMCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg2LCA5KSkgew0KICAgIGZvciAoaiBpbiAxOjMwKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gYXJyaWFnYTIwMjAgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiQXJyaWFnYSIsIGosIGksIDIwMjAsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5hcnJpYWdhMjAyMC4zMCA8LSByYmluZChuLmFycmlhZ2EyMDIwLjMwLGEpDQogICAgICAgIH0NCn0NCg0Kbi5hcnJpYWdhMjAyMC4zMSA8LSAoYXJyaWFnYTIwMjAgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNywgOCwgMTApKSB7DQogICAgZm9yIChqIGluIDE6MzEpIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSBhcnJpYWdhMjAyMCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJBcnJpYWdhIiwgaiwgaSwgMjAyMCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLmFycmlhZ2EyMDIwLjMxIDwtIHJiaW5kKG4uYXJyaWFnYTIwMjAuMzEsYSkNCiAgICAgICAgfQ0KfQ0KDQpuX2FycmlhZ2EyMDIwIDwtIG4uYXJyaWFnYTIwMjAuMzAgJT4lIA0KICB1bmlvbl9hbGwobi5hcnJpYWdhMjAyMC4zMSkNCg0KDQoNCmBgYA0KDQojIyMgQ29taXRhbg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojIGNvbWl0YW4gMjAxOCBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4uY29taXRhbjIwMTguMzAgPC0gKGNvbWl0YW4yMDE4ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDYsIDkpKSB7DQogICAgZm9yIChqIGluIDE6MzApIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSBjb21pdGFuMjAxOCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJDb21pdGFuIiwgaiwgaSwgMjAxOCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLmNvbWl0YW4yMDE4LjMwIDwtIHJiaW5kKG4uY29taXRhbjIwMTguMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLmNvbWl0YW4yMDE4LjMxIDwtIChjb21pdGFuMjAxOCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg3LCA4LCAxMCkpIHsNCiAgICBmb3IgKGogaW4gMTozMSkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIGNvbWl0YW4yMDE4ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIkNvbWl0YW4iLCBqLCBpLCAyMDE4LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4uY29taXRhbjIwMTguMzEgPC0gcmJpbmQobi5jb21pdGFuMjAxOC4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fY29taXRhbjIwMTggPC0gbi5jb21pdGFuMjAxOC4zMCAlPiUgDQogIHVuaW9uX2FsbChuLmNvbWl0YW4yMDE4LjMxKQ0KDQoNCiMgY29taXRhbiAyMDE5IHNlbGVjY2lvbmFuZG8gZWwgbWF4aW1vIGFjdW11bGFkbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kbi5jb21pdGFuMjAxOS4zMCA8LSAoY29taXRhbjIwMTkgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIGNvbWl0YW4yMDE5ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIkNvbWl0YW4iLCBqLCBpLCAyMDE5LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4uY29taXRhbjIwMTkuMzAgPC0gcmJpbmQobi5jb21pdGFuMjAxOS4zMCxhKQ0KICAgICAgICB9DQp9DQoNCm4uY29taXRhbjIwMTkuMzEgPC0gKGNvbWl0YW4yMDE5ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gY29taXRhbjIwMTkgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiQ29taXRhbiIsIGosIGksIDIwMTksIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5jb21pdGFuMjAxOS4zMSA8LSByYmluZChuLmNvbWl0YW4yMDE5LjMxLGEpDQogICAgICAgIH0NCn0NCg0Kbl9jb21pdGFuMjAxOSA8LSBuLmNvbWl0YW4yMDE5LjMwICU+JSANCiAgdW5pb25fYWxsKG4uY29taXRhbjIwMTkuMzEpDQoNCiMgYXJyaWFnYSAyMDIwIHNlbGVjY2lvbmFuZG8gZWwgbWF4aW1vIGFjdW11bGFkbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kbi5jb21pdGFuMjAyMC4zMCA8LSAoY29taXRhbjIwMjAgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIGNvbWl0YW4yMDIwICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIkNvbWl0YW4iLCBqLCBpLCAyMDIwLCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4uY29taXRhbjIwMjAuMzAgPC0gcmJpbmQobi5jb21pdGFuMjAyMC4zMCxhKQ0KICAgICAgICB9DQp9DQoNCm4uY29taXRhbjIwMjAuMzEgPC0gKGNvbWl0YW4yMDIwICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gY29taXRhbjIwMjAgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiQ29taXRhbiIsIGosIGksIDIwMjAsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5jb21pdGFuMjAyMC4zMSA8LSByYmluZChuLmNvbWl0YW4yMDIwLjMxLGEpDQogICAgICAgIH0NCn0NCg0Kbl9jb21pdGFuMjAyMCA8LSBuLmNvbWl0YW4yMDIwLjMwICU+JSANCiAgdW5pb25fYWxsKG4uY29taXRhbjIwMjAuMzEpDQoNCg0KDQpgYGANCg0KIyMjIFNhbiBjcmlzdG9iYWwgZGUgbGFzIGNhc2FzDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCiMgc2NkbGMgMjAxOCBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4uc2NkbGMyMDE4LjMwIDwtIChzY2RsYzIwMTggJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHNjZGxjMjAxOCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJzY2RsYyIsIGosIGksIDIwMTgsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5zY2RsYzIwMTguMzAgPC0gcmJpbmQobi5zY2RsYzIwMTguMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnNjZGxjMjAxOC4zMSA8LSAoc2NkbGMyMDE4ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gc2NkbGMyMDE4ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgInNjZGxjIiwgaiwgaSwgMjAxOCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnNjZGxjMjAxOC4zMSA8LSByYmluZChuLnNjZGxjMjAxOC4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fc2NkbGMyMDE4IDwtIG4uc2NkbGMyMDE4LjMwICU+JSANCiAgdW5pb25fYWxsKG4uc2NkbGMyMDE4LjMxKQ0KDQoNCiMgc2NkbGMgMjAxOSBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4uc2NkbGMyMDE5LjMwIDwtIChzY2RsYzIwMTkgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHNjZGxjMjAxOSAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJzY2RsYyIsIGosIGksIDIwMTksIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5zY2RsYzIwMTkuMzAgPC0gcmJpbmQobi5zY2RsYzIwMTkuMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnNjZGxjMjAxOS4zMSA8LSAoc2NkbGMyMDE5ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gc2NkbGMyMDE5ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgInNjZGxjIiwgaiwgaSwgMjAxOSwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnNjZGxjMjAxOS4zMSA8LSByYmluZChuLnNjZGxjMjAxOS4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fc2NkbGMyMDE5IDwtIG4uc2NkbGMyMDE5LjMwICU+JSANCiAgdW5pb25fYWxsKG4uc2NkbGMyMDE5LjMxKQ0KDQojIGFycmlhZ2EgMjAyMCBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4uc2NkbGMyMDIwLjMwIDwtIChzY2RsYzIwMjAgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHNjZGxjMjAyMCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJzY2RsYyIsIGosIGksIDIwMjAsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi5zY2RsYzIwMjAuMzAgPC0gcmJpbmQobi5zY2RsYzIwMjAuMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnNjZGxjMjAyMC4zMSA8LSAoc2NkbGMyMDIwICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gc2NkbGMyMDIwICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgInNjZGxjIiwgaiwgaSwgMjAyMCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnNjZGxjMjAyMC4zMSA8LSByYmluZChuLnNjZGxjMjAyMC4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fc2NkbGMyMDIwIDwtIG4uc2NkbGMyMDIwLjMwICU+JSANCiAgdW5pb25fYWxsKG4uc2NkbGMyMDIwLjMxKQ0KDQoNCg0KYGBgDQoNCg0KIyMjIFRhcGFjaHVsYQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KIyBUYXBhY2h1bGEgMjAxOCBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4udGFwYWNodWxhMjAxOC4zMCA8LSAodGFwYWNodWxhMjAxOCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg2LCA5KSkgew0KICAgIGZvciAoaiBpbiAxOjMwKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gdGFwYWNodWxhMjAxOCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJUYXBhY2h1bGEiLCBqLCBpLCAyMDE4LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4udGFwYWNodWxhMjAxOC4zMCA8LSByYmluZChuLnRhcGFjaHVsYTIwMTguMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnRhcGFjaHVsYTIwMTguMzEgPC0gKHRhcGFjaHVsYTIwMTggJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNywgOCwgMTApKSB7DQogICAgZm9yIChqIGluIDE6MzEpIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSB0YXBhY2h1bGEyMDE4ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIlRhcGFjaHVsYSIsIGosIGksIDIwMTgsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi50YXBhY2h1bGEyMDE4LjMxIDwtIHJiaW5kKG4udGFwYWNodWxhMjAxOC4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fdGFwYWNodWxhMjAxOCA8LSBuLnRhcGFjaHVsYTIwMTguMzAgJT4lIA0KICB1bmlvbl9hbGwobi50YXBhY2h1bGEyMDE4LjMxKQ0KDQoNCiMgVGFwYWNodWxhIDIwMTkgc2VsZWNjaW9uYW5kbyBlbCBtYXhpbW8gYWN1bXVsYWRvIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpuLnRhcGFjaHVsYTIwMTkuMzAgPC0gKHRhcGFjaHVsYTIwMTkgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNiwgOSkpIHsNCiAgICBmb3IgKGogaW4gMTozMCkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHRhcGFjaHVsYTIwMTkgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiVGFwYWNodWxhIiwgaiwgaSwgMjAxOSwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnRhcGFjaHVsYTIwMTkuMzAgPC0gcmJpbmQobi50YXBhY2h1bGEyMDE5LjMwLGEpDQogICAgICAgIH0NCn0NCg0Kbi50YXBhY2h1bGEyMDE5LjMxIDwtICh0YXBhY2h1bGEyMDE5ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDcsIDgsIDEwKSkgew0KICAgIGZvciAoaiBpbiAxOjMxKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gdGFwYWNodWxhMjAxOSAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJUYXBhY2h1bGEiLCBqLCBpLCAyMDE5LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4udGFwYWNodWxhMjAxOS4zMSA8LSByYmluZChuLnRhcGFjaHVsYTIwMTkuMzEsYSkNCiAgICAgICAgfQ0KfQ0KDQpuX3RhcGFjaHVsYTIwMTkgPC0gbi50YXBhY2h1bGEyMDE5LjMwICU+JSANCiAgdW5pb25fYWxsKG4udGFwYWNodWxhMjAxOS4zMSkNCg0KIyBUYXBhY2h1bGEgMjAyMCBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4udGFwYWNodWxhMjAyMC4zMCA8LSAodGFwYWNodWxhMjAyMCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg2LCA5KSkgew0KICAgIGZvciAoaiBpbiAxOjMwKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gdGFwYWNodWxhMjAyMCAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJUYXBhY2h1bGEiLCBqLCBpLCAyMDIwLCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4udGFwYWNodWxhMjAyMC4zMCA8LSByYmluZChuLnRhcGFjaHVsYTIwMjAuMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnRhcGFjaHVsYTIwMjAuMzEgPC0gKHRhcGFjaHVsYTIwMjAgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNywgOCwgMTApKSB7DQogICAgZm9yIChqIGluIDE6MzEpIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSB0YXBhY2h1bGEyMDIwICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIlRhcGFjaHVsYSIsIGosIGksIDIwMjAsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi50YXBhY2h1bGEyMDIwLjMxIDwtIHJiaW5kKG4udGFwYWNodWxhMjAyMC4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fdGFwYWNodWxhMjAyMCA8LSBuLnRhcGFjaHVsYTIwMjAuMzAgJT4lIA0KICB1bmlvbl9hbGwobi50YXBhY2h1bGEyMDIwLjMxKQ0KDQoNCg0KYGBgDQoNCg0KIyMjIFR1eHRsYQ0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojIFR1eHRsYSAyMDE4IHNlbGVjY2lvbmFuZG8gZWwgbWF4aW1vIGFjdW11bGFkbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kbi50dXh0bGEyMDE4LjMwIDwtICh0dXh0bGEyMDE4ICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDYsIDkpKSB7DQogICAgZm9yIChqIGluIDE6MzApIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSB0dXh0bGEyMDE4ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIlR1eHRsYSIsIGosIGksIDIwMTgsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi50dXh0bGEyMDE4LjMwIDwtIHJiaW5kKG4udHV4dGxhMjAxOC4zMCxhKQ0KICAgICAgICB9DQp9DQoNCm4udHV4dGxhMjAxOC4zMSA8LSAodHV4dGxhMjAxOCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg3LCA4LCAxMCkpIHsNCiAgICBmb3IgKGogaW4gMTozMSkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHR1eHRsYTIwMTggJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiVHV4dGxhIiwgaiwgaSwgMjAxOCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnR1eHRsYTIwMTguMzEgPC0gcmJpbmQobi50dXh0bGEyMDE4LjMxLGEpDQogICAgICAgIH0NCn0NCg0Kbl90dXh0bGEyMDE4IDwtIG4udHV4dGxhMjAxOC4zMCAlPiUgDQogIHVuaW9uX2FsbChuLnR1eHRsYTIwMTguMzEpDQoNCg0KIyBUdXh0bGEgMjAxOSBzZWxlY2Npb25hbmRvIGVsIG1heGltbyBhY3VtdWxhZG8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm4udHV4dGxhMjAxOS4zMCA8LSAodHV4dGxhMjAxOSAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg2LCA5KSkgew0KICAgIGZvciAoaiBpbiAxOjMwKSB7DQogICAgICAgICAgDQogICAgICAgIGEgPC0gdHV4dGxhMjAxOSAlPiUgDQogICAgICAgICAgICAgIGZpbHRlcihNb250aCA9PSBpICYgRGF5ID09IGopICU+JSANCiAgICAgICAgICAgICAgbXV0YXRlKGN1bV9yYWluID0gY3Vtc3VtKFJhaW4pKSAlPiUgDQogICAgICAgICAgICAgIHNsaWNlX3RhaWwobj0xKQ0KICAgICAgICANCiAgICAgICAgICBpZiAobnJvdyhhKSA9PSAwKSB7DQogICAgICAgICAgICAgIG5kIDwtZGF0YS5mcmFtZSgxNi4yMzE5NCwtOTMuOTA0NDQsIDAsICJUdXh0bGEiLCBqLCBpLCAyMDE5LCAwKQ0KICAgICAgICAgICAgICBuYW1lcyhuZCk8LW5hbWVzKGEpDQogICAgICAgICAgICAgIGEgPC0gcmJpbmQoYSwgbmQpDQogICAgICAgICAgfQ0KICAgICAgICANCiAgICAgIG4udHV4dGxhMjAxOS4zMCA8LSByYmluZChuLnR1eHRsYTIwMTkuMzAsYSkNCiAgICAgICAgfQ0KfQ0KDQpuLnR1eHRsYTIwMTkuMzEgPC0gKHR1eHRsYTIwMTkgJT4lIGFkZF9jb2x1bW4oY3VtX3JhaW4gPSBOQSkpW05VTEwsXQ0KZm9yIChpIGluIGMoNywgOCwgMTApKSB7DQogICAgZm9yIChqIGluIDE6MzEpIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSB0dXh0bGEyMDE5ICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIlR1eHRsYSIsIGosIGksIDIwMTksIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi50dXh0bGEyMDE5LjMxIDwtIHJiaW5kKG4udHV4dGxhMjAxOS4zMSxhKQ0KICAgICAgICB9DQp9DQoNCm5fdHV4dGxhMjAxOSA8LSBuLnR1eHRsYTIwMTkuMzAgJT4lIA0KICB1bmlvbl9hbGwobi50dXh0bGEyMDE5LjMxKQ0KDQojIFR1eHRsYSAyMDIwIHNlbGVjY2lvbmFuZG8gZWwgbWF4aW1vIGFjdW11bGFkbyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0Kbi50dXh0bGEyMDIwLjMwIDwtICh0dXh0bGEyMDIwICU+JSBhZGRfY29sdW1uKGN1bV9yYWluID0gTkEpKVtOVUxMLF0NCmZvciAoaSBpbiBjKDYsIDkpKSB7DQogICAgZm9yIChqIGluIDE6MzApIHsNCiAgICAgICAgICANCiAgICAgICAgYSA8LSB0dXh0bGEyMDIwICU+JSANCiAgICAgICAgICAgICAgZmlsdGVyKE1vbnRoID09IGkgJiBEYXkgPT0gaikgJT4lIA0KICAgICAgICAgICAgICBtdXRhdGUoY3VtX3JhaW4gPSBjdW1zdW0oUmFpbikpICU+JSANCiAgICAgICAgICAgICAgc2xpY2VfdGFpbChuPTEpDQogICAgICAgIA0KICAgICAgICAgIGlmIChucm93KGEpID09IDApIHsNCiAgICAgICAgICAgICAgbmQgPC1kYXRhLmZyYW1lKDE2LjIzMTk0LC05My45MDQ0NCwgMCwgIlR1eHRsYSIsIGosIGksIDIwMjAsIDApDQogICAgICAgICAgICAgIG5hbWVzKG5kKTwtbmFtZXMoYSkNCiAgICAgICAgICAgICAgYSA8LSByYmluZChhLCBuZCkNCiAgICAgICAgICB9DQogICAgICAgIA0KICAgICAgbi50dXh0bGEyMDIwLjMwIDwtIHJiaW5kKG4udHV4dGxhMjAyMC4zMCxhKQ0KICAgICAgICB9DQp9DQoNCm4udHV4dGxhMjAyMC4zMSA8LSAodHV4dGxhMjAyMCAlPiUgYWRkX2NvbHVtbihjdW1fcmFpbiA9IE5BKSlbTlVMTCxdDQpmb3IgKGkgaW4gYyg3LCA4LCAxMCkpIHsNCiAgICBmb3IgKGogaW4gMTozMSkgew0KICAgICAgICAgIA0KICAgICAgICBhIDwtIHR1eHRsYTIwMjAgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoTW9udGggPT0gaSAmIERheSA9PSBqKSAlPiUgDQogICAgICAgICAgICAgIG11dGF0ZShjdW1fcmFpbiA9IGN1bXN1bShSYWluKSkgJT4lIA0KICAgICAgICAgICAgICBzbGljZV90YWlsKG49MSkNCiAgICAgICAgDQogICAgICAgICAgaWYgKG5yb3coYSkgPT0gMCkgew0KICAgICAgICAgICAgICBuZCA8LWRhdGEuZnJhbWUoMTYuMjMxOTQsLTkzLjkwNDQ0LCAwLCAiVHV4dGxhIiwgaiwgaSwgMjAyMCwgMCkNCiAgICAgICAgICAgICAgbmFtZXMobmQpPC1uYW1lcyhhKQ0KICAgICAgICAgICAgICBhIDwtIHJiaW5kKGEsIG5kKQ0KICAgICAgICAgIH0NCiAgICAgICAgDQogICAgICBuLnR1eHRsYTIwMjAuMzEgPC0gcmJpbmQobi50dXh0bGEyMDIwLjMxLGEpDQogICAgICAgIH0NCn0NCg0Kbl90dXh0bGEyMDIwIDwtIG4udHV4dGxhMjAyMC4zMCAlPiUgDQogIHVuaW9uX2FsbChuLnR1eHRsYTIwMjAuMzEpDQoNCmBgYA0KDQoNCiMjIGJhc2UgZ2VuZXJhbA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmIyMDE4IDwtIG5fYXJyaWFnYTIwMTggJT4lIA0KICB1bmlvbl9hbGwobl9jb21pdGFuMjAxOCkgJT4lIA0KICB1bmlvbl9hbGwobl9zY2RsYzIwMTgpICU+JSANCiAgdW5pb25fYWxsKG5fdGFwYWNodWxhMjAxOCkgJT4lIA0KICB1bmlvbl9hbGwobl90dXh0bGEyMDE4KQ0KDQpiMjAxOSA8LSBuX2FycmlhZ2EyMDE5ICU+JSANCiAgdW5pb25fYWxsKG5fY29taXRhbjIwMTkpICU+JSANCiAgdW5pb25fYWxsKG5fc2NkbGMyMDE5KSAlPiUgDQogIHVuaW9uX2FsbChuX3RhcGFjaHVsYTIwMTkpICU+JSANCiAgdW5pb25fYWxsKG5fdHV4dGxhMjAxOSkNCg0KYjIwMjAgPC0gbl9hcnJpYWdhMjAyMCAlPiUgDQogIHVuaW9uX2FsbChuX2NvbWl0YW4yMDIwKSAlPiUgDQogIHVuaW9uX2FsbChuX3NjZGxjMjAyMCkgJT4lIA0KICB1bmlvbl9hbGwobl90YXBhY2h1bGEyMDIwKSAlPiUgDQogIHVuaW9uX2FsbChuX3R1eHRsYTIwMjApDQoNCg0KYjIwMTggJT4lIA0KICB1bmlvbl9hbGwoYjIwMTkpICU+JSANCiAgdW5pb25fYWxsKGIyMDIwKSAtPiBiZw0KDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmIyMDE4IDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9EYXZpZC9PbmVEcml2ZS9Eb2N1bWVudG9zL01NQS9zZW1pbmFyaW8gZGUgdGVzaXMgMi9hdmFuY2VzIHNlbWluYXJpby9kYXRvcy9iYXNlL0NoaWFwYXMgNS9zdW1tZXIvZGF0YS9uZC9iMjAxOC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQpiMjAxOSA8LSByZWFkLmNzdigiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vZGF0b3MvYmFzZS9DaGlhcGFzIDUvc3VtbWVyL2RhdGEvbmQvYjIwMTkuY3N2IiwgaGVhZGVyID0gVFJVRSkNCg0KYjIwMjAgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL0RhdmlkL09uZURyaXZlL0RvY3VtZW50b3MvTU1BL3NlbWluYXJpbyBkZSB0ZXNpcyAyL2F2YW5jZXMgc2VtaW5hcmlvL2RhdG9zL2Jhc2UvQ2hpYXBhcyA1L3N1bW1lci9kYXRhL25kL2IyMDIwLmNzdiIsIGhlYWRlciA9IFRSVUUpDQoNCmJnIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9EYXZpZC9PbmVEcml2ZS9Eb2N1bWVudG9zL01NQS9zZW1pbmFyaW8gZGUgdGVzaXMgMi9hdmFuY2VzIHNlbWluYXJpby9kYXRvcy9iYXNlL0NoaWFwYXMgNS9zdW1tZXIvZGF0YS9uZC9iZy5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KDQoNCiMgYjIwMTggPC0gYjIwMTggJT4lIHNlbGVjdCgtUmFpbikNCiMgYjIwMTkgPC0gYjIwMTkgJT4lIHNlbGVjdCgtUmFpbikNCiMgYjIwMjAgPC0gYjIwMjAgJT4lIHNlbGVjdCgtUmFpbikNCiMgYmcgPC0gYmcgJT4lIHNlbGVjdCgtUmFpbikNCmBgYA0KDQoNCiMgRURBIGZhc3QNCg0Kb2JzZXJ2ZW1vcyB1biBwb2NvIG51ZXN0cmFzIGJhc2VzIGRlIGRhdG9zLCBhbGd1bmFzIGVzdGFkaXN0aWNhcyBkZXNjcmlwdGl2YXMNCg0KYGBge3IsIGNhY2hlPVRSVUV9DQpsaWJyYXJ5KGVsdWNpZGF0ZSkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KDQoNCmIyMDE4ICU+JSANCiAgZ2xpbXBzZSgpICU+JSANCiAgZGVzY3JpYmUoeSA9IFJhaW4pDQpiMjAxOCAlPiUgDQogIHBsb3RfZGVuc2l0eSh4ID0gUmFpbiwNCiAgICAgICAgICAgICAgIHRpdGxlID0gIjIwMTggYmFzaWMgZGVuc2l0eSBwbG90IG9mIFJhaW4iLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJsaWdodHNlYWdyZWVuIikgLT4gcDE7cDENCg0KYjIwMTkgJT4lIA0KICBnbGltcHNlKCkgJT4lIA0KICBkZXNjcmliZSh5ID0gUmFpbikNCmIyMDE5ICU+JSANCiAgcGxvdF9kZW5zaXR5KHggPSBSYWluLA0KICAgICAgICAgICAgICAgdGl0bGUgPSAiMjAxOSBiYXNpYyBkZW5zaXR5IHBsb3Qgb2YgUmFpbiIsDQogICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0c2t5Ymx1ZSIpIC0+IHAyO3AyDQoNCmIyMDIwICU+JSANCiAgZ2xpbXBzZSgpICU+JSANCiAgZGVzY3JpYmUoeSA9IFJhaW4pDQpiMjAyMCAlPiUgDQogIHBsb3RfZGVuc2l0eSh4ID0gUmFpbiwNCiAgICAgICAgICAgICAgIHRpdGxlID0gIjIwMjAgYmFzaWMgZGVuc2l0eSBwbG90IG9mIFJhaW4iLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJvbGl2ZWRyYWIzIikgLT4gcDM7cDMNCg0KDQpiZyAlPiUgDQogIGdsaW1wc2UoKSAlPiUgDQogIGRlc2NyaWJlKHkgPSBSYWluKQ0KYmcgJT4lIA0KICBwbG90X2RlbnNpdHkoeCA9IFJhaW4sDQogICAgICAgICAgICAgICB0aXRsZSA9ICIoMjAxOC0yMDIwKSBiYXNpYyBkZW5zaXR5IHBsb3QgZ2VuZXJhbCBvZiBSYWluIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAic2FsbW9uMSIpIC0+IHA0O3A0DQoNCihwMSArIHAyKS8ocDMgKyBwNCkNCg0KYGBgDQoNCg0KYGBge3J9DQpiMjAxOCAlPiUgDQogIGdncGxvdChhZXMoeCA9IERheSwgeSA9IFJhaW4sIGNvbG9yPWZhY3RvcihNb250aCkpKSArDQogICMgZ2VvbV9wb2ludCgpICsNCiAgZmFjZXRfd3JhcCh+U3RhdGlvbiwgc2NhbGVzPSJmcmVlIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgZ2VvbV9saW5lKCkgKyANCiAgZ2d0aXRsZSgiTWF4aW1vcyBwYXJhIGVsIDIwMTgiKQ0KDQpiMjAxOSAlPiUgDQogIGdncGxvdChhZXMoeCA9IERheSwgeSA9IFJhaW4sIGNvbG9yPWZhY3RvcihNb250aCkpKSArDQogICMgZ2VvbV9wb2ludCgpICsNCiAgZmFjZXRfd3JhcCh+U3RhdGlvbiwgc2NhbGVzPSJmcmVlIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgZ2VvbV9saW5lKCkgKyANCiAgZ2d0aXRsZSgiTWF4aW1vcyBwYXJhIGVsIDIwMTkiKQ0KDQpiMjAyMCAlPiUgDQogIGdncGxvdChhZXMoeCA9IERheSwgeSA9IFJhaW4sIGNvbG9yPWZhY3RvcihNb250aCkpKSArDQogICMgZ2VvbV9wb2ludCgpICsNCiAgZmFjZXRfd3JhcCh+U3RhdGlvbiwgc2NhbGVzPSJmcmVlIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgZ2VvbV9saW5lKCkgKyANCiAgZ2d0aXRsZSgiTWF4aW1vcyBwYXJhIGVsIDIwMjAiKQ0KDQpiZyAlPiUgDQogIGdncGxvdChhZXMoeCA9IERheSwgeSA9IFJhaW4sIGNvbG9yPWZhY3RvcihNb250aCkpKSArDQogICMgZ2VvbV9wb2ludCgpICsNCiAgZmFjZXRfd3JhcCh+U3RhdGlvbiArIHllYXIsIHNjYWxlcz0iZnJlZSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGdlb21fbGluZSgpICsgDQogIGdndGl0bGUoIk1heGltb3MgcGFyYSBlbCAyMDE4LTIwMjAiKQ0KYGBgDQoNCiMgZ3JhZmljYSBkZSBsb3MgZGF0b3MNCg0KQWhvcmEgY3JlZW1vcyAzIGdyYWZpY29zIHBhcmEgY2FkYSBhw7FvIGNvcnJlc3BvbmRpZW50ZSBkZSBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zLCBjYXJnZW1vcyBhbGd1bmFzIGxpYnJlcmlhcyBuZWNlc2FyaWFzDQoNCkxhIHNpZ3VpZW50ZSBmb3JtYSBkZSBtYXBlYXIgbnVlc3RybyBjb25qdW50byBkZSBkYXRvcyBvYnRlbmlkbywgZXMgZGUgbGEgc2lndWllbnRlIGZvcm1hLCBjb25zaWRlcmUgcXVlIGVzdGEgZm9ybWEgbm8gaW52b2x1Y3JhIGxlZXIgdW4gc2hhcGUgZmlsZSwgY29udmVydGlyIGxvcyBkYXRvcyBhIHRpcG8gZ2VvZGF0YSB5IHRvZGFzIGVzYXMgcGFydGljdWxhcmlkYWRlcywgZXNvIGVzIGxvIGludGVyZXNhbnRlIHkgcHJhY3RpY28sIGF1bnF1ZSBubyBkZXNjYXJ0YW1vcyBoYWNlcmxvIGRlIGxhIGZvcm1hIGNvcnJlc3BvbmRpZW50ZS4NCg0KQWxnbyBwYXJ0aWN1bGFyIGVzIHF1ZSBzaSBuZWNlc2l0YW1vcyBlbCBzaGFwZSBmaWxlLCBzb2xvIHBhcmEgY29sb2NhciBlbCBjb250b3JubyBkZWwgZXN0YWRvIGRlIGNoaWFwYXMsIGVzIHBvciBlbGxvIHF1ZSBkZWJlbW9zIGRlIGxlZXJsby4NCg0KY2FyZ2Ftb3MgYWxndW5hcyBsaWJyZXJpYXMNCg0KDQpgYGB7cn0NCmxpYnJhcnkocmdkYWwpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShsZWFmbGV0KSAgICAgICMgbGlicmVyaWEgcGFyYSBncmFmaWNhciBtYXBhcyBpbnRlcmFjdGl2b3MNCmxpYnJhcnkoc2YpICAgICAgICAgICAjIG1hbmVqbyBkZSBpbmZvcm1hY2lvbiBnZW9ncmFmaWNhIA0KbGlicmFyeSh2aXJpZGlzKSAgICAgICMgcGFsZXRhcyBkZSBjb2xvcmVzDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgIyBtYXMgcGFsZXRhcyBkZSBjb2xvcmVzDQpsaWJyYXJ5KHBhdGNod29yaykNCmBgYA0KDQoNCmEgY29udGludWFjacOzbiBsZWVtb3MgbnVlc3RybyBhcmNoaXZvIHNoYXBlZmlsZSwgYWxnbyBxdWUgZGViZW1vcyBpZGVudGlmaWNhciBkZWwgc2hhcGVmaWxlIGVzIHF1ZSBzdSBwcm95ZWNjaW9uIGdlb2dyYWZpY2Egbm8gY29pbmNpZGUgY29uIGxhIHByb3llY2Npb24gZ2VvZ3JhZmljYSBkZWwgY29uanVudG8gZGUgZGFvcyBhIHRyYWJhamFyLCBlcyBwb3IgZWxsbyBxdWUgc2UgbmVjZXNpdGEgcmVhbGl6YXIgdW5hIHRyYW5zZm9ybWFjacOzbiBlbiBsYSBwcm95ZWNjacOzbiBkZSBudWVzdHJvIHNoYXBlZmlsZSwgcGFyYSBsbGV2YXJsbyBhIGxhIHByb3llY2Npw7NuIGhhYml0dWFsIGRlIGxvbmdpdHVkIHkgbGF0aXR1ZCBxdWUgc2UgY29ub2NlLg0KDQoNCmBgYHtyLCBjYWNoZT1UUlVFfQ0KbXlfc3BkZiA8LSByZWFkT0dSKCANCiAgZHNuPSAiQzovVXNlcnMvRGF2aWQvT25lRHJpdmUvRG9jdW1lbnRvcy9NTUEvc2VtaW5hcmlvIGRlIHRlc2lzIDIvYXZhbmNlcyBzZW1pbmFyaW8vQTIiLCANCiAgbGF5ZXI9IkVOVElEQUQiLA0KICB2ZXJib3NlPUZBTFNFDQopDQoNCiMgdHJhc2Zvcm1hbW9zIGEgZWwgc2lzdGVtYSBkZSBjb29yZGVuYWRhcyBoYWJpdHVhbA0KDQpteV9zcGRmIDwtIHNwVHJhbnNmb3JtKG15X3NwZGYsIENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkNCmBgYA0KDQp5IHNlbGVjY2lvbmFtb3MgZWwgZXN0YWRvIGRlIGNoaWFwYXMNCg0KYGBge3J9DQpteV9zcGRmX2MgPC0gbXlfc3BkZltteV9zcGRmJG5vbWJyZSA9PSAiQ0hJQVBBUyIsXQ0KYGBgDQoNCnBvZGVtb3Mgb2JzZXJ2YXIgbWVkaWFudGUgdW4gZ3JhZmljbyBxdWUgZWwgZXN0YWRvIHNlbGVjY2lvbmFkbyBzZWEgZWwgY29ycmVjdG8uDQoNCmBgYHtyfQ0KcGxvdChteV9zcGRmX2MsIGNvbD0iI2YyZjJmMiIsIGJnPSJza3libHVlIiwgbHdkPTAuMjUpDQpgYGANCg0KQWhvcmEgc2kgZXN0YW1vcyBsaXN0b3MgcGFyYSByZWFsaXphciB1biBncmFmaWNvIGRlIG51ZXN0cm8gY29uanVudG8gZGUgZGF0b3MNCg0KYGBge3IsIGNhY2hlPVRSVUUsIGV2YWw9RkFMU0V9DQpiMjAxOCAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgY29sb3VyID0gUmFpbiksc2l6ZSA9MykrDQogIGJvcmRlcnMobXlfc3BkZl9jKSsNCiAgY29vcmRfcXVpY2ttYXAoKSsNCiAgdGhlbWVfdGVzdCgpDQpgYGANCg0KQWdyZWdhbmRvIHVuIHBvY28gbWFzIGRlIGRldGFsbGUgcG9kZW1vcyBvYnRlbmVyIHVuIGdyYWZpY28gbWFzIGRldGFsbGFkbyBwYXJhIGNhZGEgYcOxbyB5IGdlbmVyYWwNCg0KYGBge3IsIGNhY2hlPVRSVUUsIGV2YWw9RkFMU0V9DQpsaWJyYXJ5KGdncmVwZWwpDQoNCmIyMDE4ICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gTG9uZ2l0dWQsIHkgPSBMYXRpdHVkKSkgKw0KICBib3JkZXJzKG15X3NwZGZfYywgZmlsbCA9ICJhbnRpcXVld2hpdGUxIikgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBSYWluKSwgc2l6ZSA9IDQpICsNCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiLCB0cmFucyA9ICJzcXJ0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgIG9vYiA9IHNjYWxlczo6c3F1aXNoKSArDQogIGNvb3JkX3F1aWNrbWFwKCkgKw0KICB0aGVtZV90ZXN0KCkgICsNCiAgeGxhYigiTG9uZ2l0dWRlIikgKyB5bGFiKCJMYXRpdHVkZSIpICsNCiAgZ2d0aXRsZSgiQ2hpYXBhcyAyMDE4Iiwgc3VidGl0bGUgPSAiUHJlY2lwaXRhY2nDs24gbWVkaWEgcG9yIGhvcmEiKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSBncmF5KDAuNSksIGxpbmV0eXBlID0gImRhc2hlZCIsIA0KICAgICAgICBzaXplID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImFsaWNlYmx1ZSIpKSArDQogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gZGlzdGluY3QoYjIwMTgsIExvbmdpdHVkLCAua2VlcF9hbGwgPSBUUlVFKSwgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgbGFiZWwgPSBTdGF0aW9uKSwNCiAgICAgICAgICAgICAgICAgIGJveC5wYWRkaW5nICAgPSAxLCBwb2ludC5wYWRkaW5nID0gMSwgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDQsIHBvaW50LnNpemUgPSA0LCBzZWdtZW50LnNpemUgPSAxKSAtPiBwNTtwNQ0KDQojIHVuaXF1ZShiMjAxOCRTdGF0aW9uKQ0KIyBkaXN0aW5jdChiMjAxOCwgTG9uZ2l0dWQsIC5rZWVwX2FsbCA9IFQpDQojIHRhYmxlKGIyMDE4JExhdGl0dWQpDQpiMjAxOSAlPiUgDQogIGdncGxvdCgpICsNCiAgYm9yZGVycyhteV9zcGRmX2MsIGZpbGwgPSAiYW50aXF1ZXdoaXRlMSIpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgY29sb3IgPSBSYWluLCBsYWJlbD1TdGF0aW9uKSwgc2l6ZSA9NCkgKw0KICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGRpc3RpbmN0KGIyMDE5LCBTdGF0aW9uLCAua2VlcF9hbGwgPSBUUlVFKSwgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgbGFiZWwgPSBTdGF0aW9uKSwNCiAgICAgICAgICAgICAgICAgIGJveC5wYWRkaW5nICAgPSAxLCBwb2ludC5wYWRkaW5nID0gMSwgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnLA0KICAgICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsIHNpemUgPSA0LCBwb2ludC5zaXplID0gNCwgc2VnbWVudC5zaXplID0gMSkrDQogIGNvb3JkX3F1aWNrbWFwKCkgKw0KICB0aGVtZV90ZXN0KCkgICsNCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiLCB0cmFucyA9ICJzcXJ0IikgKw0KICB4bGFiKCJMb25naXR1ZGUiKSArIHlsYWIoIkxhdGl0dWRlIikgKw0KICBnZ3RpdGxlKCJDaGlhcGFzIDIwMTkiLCBzdWJ0aXRsZSA9ICJQcmVjaXBpdGFjacOzbiBtZWRpYSBwb3IgaG9yYSIpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9IGdyYXkoMC41KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuNSksIA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiYWxpY2VibHVlIikpIC0+IHA2O3A2DQoNCg0KYjIwMjAgJT4lIA0KZ2dwbG90KCkgKw0KICBib3JkZXJzKG15X3NwZGZfYywgZmlsbCA9ICJhbnRpcXVld2hpdGUxIikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gTG9uZ2l0dWQsIHkgPSBMYXRpdHVkLCBjb2xvciA9IFJhaW4sIGxhYmVsID0gU3RhdGlvbiksIHNpemUgPTQpICsNCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBkaXN0aW5jdChiMjAyMCwgU3RhdGlvbiwgLmtlZXBfYWxsID0gVFJVRSksIA0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBMb25naXR1ZCwgeSA9IExhdGl0dWQsIGxhYmVsID0gU3RhdGlvbiksDQogICAgICAgICAgICAgICAgICBib3gucGFkZGluZyAgID0gMSwgcG9pbnQucGFkZGluZyA9IDEsIHNlZ21lbnQuY29sb3IgPSAnZ3JleTUwJywNCiAgICAgICAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCBzaXplID0gNCwgcG9pbnQuc2l6ZSA9IDQsIHNlZ21lbnQuc2l6ZSA9IDEpKyAgDQogIGNvb3JkX3F1aWNrbWFwKCkgKw0KICB0aGVtZV90ZXN0KCkgICsNCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKG9wdGlvbiA9ICJwbGFzbWEiLCB0cmFucyA9ICJzcXJ0IikgKw0KICB4bGFiKCJMb25naXR1ZGUiKSArIHlsYWIoIkxhdGl0dWRlIikgKw0KICBnZ3RpdGxlKCJDaGlhcGFzIDIwMjAiLCBzdWJ0aXRsZSA9ICJQcmVjaXBpdGFjacOzbiBtZWRpYSBwb3IgaG9yYSIpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9IGdyYXkoMC41KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgDQogICAgICAgIHNpemUgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiYWxpY2VibHVlIikpIC0+IHA3O3A3DQoNCmJnICU+JSANCmdncGxvdCgpICsNCiAgYm9yZGVycyhteV9zcGRmX2MsIGZpbGwgPSAiYW50aXF1ZXdoaXRlMSIpICsNCiAgZ2VvbV9wb2ludChhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgY29sb3IgPSBSYWluLCBsYWJlbD1TdGF0aW9uKSwgc2l6ZSA9NCkgKw0KICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGRpc3RpbmN0KGIyMDIwLCBTdGF0aW9uLCAua2VlcF9hbGwgPSBUUlVFKSwgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IExvbmdpdHVkLCB5ID0gTGF0aXR1ZCwgbGFiZWwgPSBTdGF0aW9uKSwNCiAgICAgICAgICAgICAgICAgIGJveC5wYWRkaW5nICAgPSAxLCBwb2ludC5wYWRkaW5nID0gMSwgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnLA0KICAgICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsIHNpemUgPSA0LCBwb2ludC5zaXplID0gNCwgc2VnbWVudC5zaXplID0gMSkrICAgIA0KICBjb29yZF9xdWlja21hcCgpICsNCiAgdGhlbWVfdGVzdCgpICArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIiwgdHJhbnMgPSAic3FydCIpICsNCiAgeGxhYigiTG9uZ2l0dWRlIikgKyB5bGFiKCJMYXRpdHVkZSIpICsNCiAgZ2d0aXRsZSgiQ2hpYXBhcyAyMDE4LTIwMjAiLCBzdWJ0aXRsZSA9ICJQcmVjaXBpdGFjacOzbiBtZWRpYSBwb3IgaG9yYSIpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9IGdyYXkoMC41KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgDQogICAgICAgIHNpemUgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiYWxpY2VibHVlIikpIC0+IHA4O3A4DQoNCihwNSArIHA2KS8ocDcgKyBwOCkNCg0KYGBgDQoNCg0KIyBwcnVlYmEgZXN0YWRpc3RpY2EgZm9ybWFsIHBhcmEgdmVyaWZpY2FyIHNpIG1pcyBkYXRvcyBzb24gZGUgR0VWDQoNCkFsZ28gaW1wb3J0YW50ZSBlcyBkZXRlcm1pbmFyIHNpIG1pIGNvbmp1bnRvIGRlIGRhdG9zIHNpZ3VlIHVuYSBHRVZELCBlc3RvIHNlIHJlYWxpemEgZGUgbGEgc2lndWllbnRlIGZvcm1hLg0KDQrCv1F1ZSByZWFsaXphIGVzdGUgcGFxdWV0ZT8NCg0KQ2FsY3VsYSBlbCBlc3RhZMOtc3RpY28gZGUgcHJ1ZWJhIHkgZWwgdmFsb3IgcCBkZSBsYSBwcnVlYmEgZGUgQ3JhbWVyLXZvbiBNaXNlcyB5IEFuZGVyc29uIERhcmxpbmcgcGFyYSBhbGd1bmFzIGZ1bmNpb25lcyBkZSBkaXN0cmlidWNpw7NuIGNvbnRpbnVhIHByb3B1ZXN0YXMgcG9yIENoZW4geSBCYWxha3Jpc2huYW4gKDE5OTUpIFtodHRwOi8vYXNxLm9yZy9xaWMvZGlzcGxheS1pdGVtL2luZGV4Lmh0bWw/aXRlbT0gMTE0MDddLiBBZGVtw6FzIGRlIG51ZXN0cmFzIGZ1bmNpb25lcyBkZSBkaXN0cmlidWNpw7NuIGNsw6FzaWNhcyBhcXXDrSwgY2FsY3VsYW1vcyBsYSBwcnVlYmEgZGUgYm9uZGFkIGRlIGFqdXN0ZSAoR29GKSBwYXJhIGVsIGNvbmp1bnRvIGRlIGRhdG9zIHF1ZSBzaWd1ZSBsYSBmdW5jacOzbiBkZSBkaXN0cmlidWNpw7NuIGRlIHZhbG9yIGV4dHJlbW8sIHNpbiByZWNvcmRhciBsYSBmw7NybXVsYSBkZSBsYXMgZnVuY2lvbmVzIGRlIGRpc3RyaWJ1Y2nDs24vZGVuc2lkYWQuIENhbGN1bGEgZWwgdmFsb3IgZW4gcmllc2dvIChWYVIpIHkgZWwgVmFSIHByb21lZGlvIHNvbiBvdHJvcyBmYWN0b3JlcyBkZSByaWVzZ28gaW1wb3J0YW50ZXMgcXVlIHNlIGVzdGltYW4gbWVkaWFudGUgZWwgdXNvIGRlIGZ1bmNpb25lcyBkZSBkaXN0cmlidWNpw7NuIGJpZW4gY29ub2NpZGFzLiBQZmx1ZyB5IFJvbWlzY2ggKDIwMDcsIElTQk46IDk4MTI3MDc0MDkpIGVzIHVuYSBidWVuYSByZWZlcmVuY2lhIHBhcmEgZXN0dWRpYXIgbGFzIHByb3BpZWRhZGVzIGRlIGxhcyBtZWRpZGFzIGRlIHJpZXNnby4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQoiZ2VuLmdldiIgPC0NCmZ1bmN0aW9uKHAsIG4sIHRyZW5kPU5VTEwpIHsNCg0KIyBzaW11bGF0ZXMgZ2V2IGRhdGEgdXNpbmcgYW4gZXhwb25lbnRpYWwNCiMgcCBpcyBjKG11LCBzaWdtYSwgZ2FtbWEpDQojIHJvdXRpbmUgYnkgR1kNCg0KaWYoIHBbM10gIT0gMCkgew0KIyBHZW5lcmF0ZSBmcm9tIGEgR0VWIGRpc3RyaWJ1dGlvbiAoRnJlY2hldCBvciBXZWlidWxsKQ0KIwl4IDwtIHJleHAobikNCiMJaWYoIGlzLm51bGwodHJlbmQpKSBnZXYuZGF0IDwtIHBbMV0gKyBwWzJdKih4XigtcFszXSktMSkvcFszXQ0KCWlmKCBpcy5udWxsKHRyZW5kKSkNCgkJZ2V2LmRhdCA8LSBwWzFdICsgcFsyXSooKC1sb2cocnVuaWYobikpKV4oLXBbM10pLTEpL3BbM10NCgllbHNlIHsNCg0KICAgICMgZ2VuZXJhdGUgZ2V2IHdpdGggYSBsaW5lYXIgdHJlbmQgaW4gbXUNCiAgICBnZXYuZGF0PC1udW1lcmljKG4pDQojIGZvciggaSBpbiAxOm4pIGdldi5kYXRbaV0gPC0gcFsxXStpKnRyZW5kK3BbMl0qKHhbaV1eKC1wWzNdKS0xKS9wWzNdDQpmb3IoIGkgaW4gMTpuKQ0KCWdldi5kYXRbaV0gPC0gcFsxXStpKnRyZW5kK3BbMl0qKCgtbG9nKHJ1bmlmKG4pW2ldKSleKC1wWzNdKS0xKS9wWzNdDQoJCX0NCn0gZWxzZSB7DQoJIyBHZW5lcmF0ZSBmcm9tIGEgR3VtYmVsIGRpc3RyaWJ1dGlvbg0KCWlmKCBpcy5udWxsKCB0cmVuZCkpIGdldi5kYXQgPC0gcFsxXSAtIHBbMl0qbG9nKCAtbG9nKCBydW5pZihuKSkpDQoJZWxzZSB7DQoJCWdldi5kYXQgPC0gbnVtZXJpYyhuKQ0KZm9yKCBpIGluIDE6bikgZ2V2LmRhdFtpXSA8LSBwWzFdICsgaSp0cmVuZCAtIHBbMl0qbG9nKCAtbG9nKCBydW5pZihuKVtpXSkpDQoJCX0NCgl9ICMgZW5kIG9mIGlmIGVsc2UgcCBpcyBub3QgMCBzdG10DQpyZXR1cm4oIGdldi5kYXQpDQp9ICMgZW5kIG9mIGdlbi5nZXYgZmNuDQoNCmhpc3QuZ2V2LmZpdCA8LSBmdW5jdGlvbih4LCBicmVha3MubWV0aG9kPSJTdHVyZ2VzIiwuLi4pDQp7DQphIDwtIHgkbWxlDQpkYXQgPC0geCRkYXRhDQojDQojIFBsb3RzIGhpc3RvZ3JhbSBvZiBkYXRhIGFuZCBmaXR0ZWQgZGVuc2l0eQ0KIyBmb3Igb3V0cHV0IG9mIGdldi5maXQgc3RvcmVkIGluIHoNCiMNCiAgICAgICAgaCA8LSBoaXN0KGRhdCwgZnJlcSA9IEZBTFNFLCBicmVha3M9YnJlYWtzLm1ldGhvZCwgcGxvdCA9IEZBTFNFLC4uLikNCiAgICAgICAgaWYoYVszXSA8IDApIHsNCiAgICAgICAgICAgICAgICB4MSA8LSBzZXEobWluKGgkYnJlYWtzKSwgbWluKG1heChoJGJyZWFrcyksIChhWzFdIC0gYVsyXS9hWzNdIC0NCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDAxKSksIGxlbmd0aCA9IDEwMCkNCiAgICAgICAgfQ0KICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICB4MSA8LSBzZXEobWF4KG1pbihoJGJyZWFrcyksIChhWzFdIC0gYVsyXS9hWzNdICsgMC4wMDEpKSwgbWF4KGgkDQogICAgICAgICAgICAgICAgICAgICAgICBicmVha3MpLCBsZW5ndGggPSAxMDApDQogICAgICAgIH0NCiAgICAgICAgeSA8LSBnZXYuZGVucyhhLCB4MSkNCiAgICAgICAgaGlzdChkYXQsIGZyZXEgPSBGQUxTRSwgYnJlYWtzPWJyZWFrcy5tZXRob2QsIHlsaW0gPSBjKDAsIG1heCh5KSksIHhsYWIgPSAieiIsIHlsYWIgPSAiZih6KSIsDQogICAgICAgICAgICAgICAgbWFpbiA9ICJEZW5zaXR5IFBsb3QiLC4uLikNCiAgICAgICAgcG9pbnRzKGRhdCwgcmVwKDAsIGxlbmd0aChkYXQpKSkNCiAgICAgICAgbGluZXMoeDEsIHkpDQppbnZpc2libGUoaCkNCn0gDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGduRml0KQ0KbGlicmFyeShmRXh0cmVtZXMpDQpsaWJyYXJ5KGV4dFJlbWVzKQ0KbGlicmFyeShpc21ldikNCmBgYA0KDQpQYXJhIHByb2JhciBIMDogWDEsLiAuIC4gLCBYbiBlcyB1bmEgbXVlc3RyYSBhbGVhdG9yaWEgZGUgdW5hIGRpc3RyaWJ1Y2nDs24gY29udGludWEgY29uIGZ1bmNpw7NuIGRlIGRpc3RyaWJ1Y2nDs24gYWN1bXVsYXRpdmEgRiAoeDsgzrgpLCBkb25kZSBzZSBjb25vY2UgbGEgZm9ybWEgZGUgRiBwZXJvIHNlIGRlc2Nvbm9jZSDOuC4gUHJpbWVybyBlc3RpbWFtb3MgzrggcG9yICTOuF7iiJckIChwb3IgZWplbXBsbywgbcOpdG9kbyBkZSBlc3RpbWFjacOzbiBkZSBtw6F4aW1hIHZlcm9zaW1pbGl0dWQpLiBBIGNvbnRpbnVhY2nDs24sIGNhbGN1bGFtb3MgdmkgPSBGICh4aSwgzrjiiJcpLCBkb25kZSBsb3MgeGkgZXN0w6FuIGVuIG9yZGVuIGFzY2VuZGVudGUuDQoNCg0KIyMgY29uIG1pcyBkYXRvcw0KDQpzZWxlY2Npb25lbW9zIGxvcyB2YWxvcmVzIG1heW9yZXMgYSAyOSBkZSBsYSBwcmVjaXBpdGFjacOzbiBwb3IgaG9yYSBlc3RvIGNvbiByZXNwZWN0byBhIGluZm9ybWFjacOzbiBxdWUgc2UgbWVuY2lvbm8gYWwgY29taWVuem8uDQoNCg0KYGBge3J9DQpuZCA8LSBiZyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoUmFpbikgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKFJhaW4gPiAzMCkNCg0KIyBuZF9tID0gZ2V2U2ltKG1vZGVsID0gbGlzdCh4aSA9IDAuMjUsIG11ID0gMCAsIGJldGEgPSAxKSwgbiA9IDEwMDApDQojIGZpdDEgID0gZ2V2Rml0KHgxLCB0eXBlID0gIm1sZSIpIA0KbmRfbSA8LSBnZXYuZml0KGFzLnZlY3Rvcihhcy5udW1lcmljKGFzLm1hdHJpeChuZCkpKSkNCg0KZ2V2LmRpYWcobmRfbSkNCmBgYA0KDQoNCmBgYHtyLCBtZXNzYWdlPVRSVUV9DQojIGZpdDFAZml0W2MoNiwgNywgMywgNCldDQpnbmZpdChhcy5udW1lcmljKGFzLm1hdHJpeChuZCkpLCAiZ2V2IiwgcHIgPSBuZF9tJG1sZSkNCg0KbmRfbTEgPC0gZ2V2Rml0KG5kLCB0eXBlID0gIm1sZSIpDQpwcmludChuZF9tMSkNCiAgIA0KIyMgc3VtbWFyeSAtDQogICAjIFN1bW1hcml6ZSBSZXN1bHRzOg0KICAgcGFyKG1mY29sID0gYygyLCAyKSkNCiAgIHN1bW1hcnkobmRfbTEpDQoNCg0KYGBgDQoNCg0KDQoNCg0KDQojIGFqdXN0ZSBkZSBEYXZpc29uLCBBLkMuLCBQYWRvYW4sIFMuQS4gYW5kIFJpYmF0ZXQNCg0KTGEgc2lndWllbnRlIG1ldG9kb2xvZ2lhIGVzIGNvbmZvcm1lIGFsIGFqdXN0ZSBkZSBEYXZpc29uLCBBLkMuLCBQYWRvYW4sIFMuQS4gYW5kIFJpYmF0ZXQuDQoNCg0KTGEgZnVuY2nDs24gcGFyYSBpbmNvcnBvcmFyIGVsIGNvbXBvbmVudGUgdGVtcG9yYWwgeSBzcGF0aWFsIGEgdW5hIERWRUcgZXMgbGEgZnVuY2nDs24gYGxhdGVudGAgZGUgbGEgbGlicmVyaWEgYFNwYXRpYWxFeHRyZW1lc2AsIGxhIGN1YWwgaW5kaWNhIGxvIHNpZ3VpZW50ZToNCg0KYGxhdGVudGA6IE1vZGVsb3MgamVyw6FycXVpY29zIGJheWVzaWFub3MgcGFyYSBleHRyZW1vcyBlc3BhY2lhbGVzDQoNCioqRGVzY3JpcGNpw7NuKioNCg0KRXN0YSBmdW5jacOzbiBnZW5lcmEgdW5hIGNhZGVuYSBkZSBNYXJrb3YgYSBwYXJ0aXIgZGUgdW4gbW9kZWxvIGplcsOhcnF1aWNvIGJheWVzaWFubyBwYXJhIGJsb3F1ZXMgbcOheGltb3MgYXN1bWllbmRvIGluZGVwZW5kZW5jaWEgY29uZGljaW9uYWwuDQoNCioqVXNvKioNCg0KYGBge3IsIGV2YWw9RkFMU0UsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLXNob3cnfQ0KbGF0ZW50KGRhdGEsIGNvb3JkLCBjb3YubW9kID0gInBvd2V4cCIsIGxvYy5mb3JtLCBzY2FsZS5mb3JtLA0Kc2hhcGUuZm9ybSwgbWFyZy5jb3YgPSBOVUxMLCBoeXBlciwgcHJvcCwgc3RhcnQsIG4gPSA1MDAwLCB0aGluID0gMSwNCmJ1cm4uaW4gPSAwLCB1c2UubG9nLmxpbmsgPSBGQUxTRSkNCmBgYA0KDQoqKkFyZ3VtZW50b3MqKg0KDQpgZGF0YWA6IFVuYSBtYXRyaXogcXVlIHJlcHJlc2VudGEgbG9zIGRhdG9zLiBDYWRhIGNvbHVtbmEgY29ycmVzcG9uZGUgYSB1bmEgdWJpY2FjacOzbi4NCg0KYGNvb3JkOmAgVW5hIG1hdHJpeiBxdWUgZGEgbGFzIGNvb3JkZW5hZGFzIGRlIGNhZGEgdWJpY2FjacOzbi4gQ2FkYSBmaWxhIGNvcnJlc3BvbmRlIGEgdW5hIHViaWNhY2nDs24uDQoNCmBjb3YubW9kZWw6YCBDYWRlbmEgZGUgY2FyYWN0ZXJlcyBjb3JyZXNwb25kaWVudGUgYWwgbW9kZWxvIGRlIGNvdmFyaWFuemEgZGUgbG9zIHByb2Nlc29zIGxhdGVudGVzIGdhdXNzaWFub3MuIERlYmUgc2VyIHVubyBkZSAiZ2F1c3MiIHBhcmEgZWwgbW9kZWxvIGRlIFNtaXRoOyAid2hpdG1hdCIsICJjYXVjaHkiLCAicG93ZXhwIiBvICJiZXNzZWwiIG8gcGFyYSBsYXMgZmFtaWxpYXMgZGUgY29ycmVsYWNpw7NuIFdoaXR0bGUtTWF0ZXJuLCBDYXVjaHksIFBvd2VyZWQgRXhwb25lbnRpYWwgeSBCZXNzZWwuDQoNCmBsb2MuZm9ybSwgc2NhbGUuZm9ybSwgc2hhcGUuZm9ybWA6IEbDs3JtdWxhcyBSIHF1ZSBkZWZpbmVuIGxvcyBtb2RlbG9zIGVzcGFjaWFsZXMgcGFyYSBsb3MgcGFyw6FtZXRyb3MgR0VWLiBDb25zdWx0ZSBsYSBzZWNjacOzbiBEZXRhbGxlcy4NCg0KYG1hci5jb3Y6YCBNYXRyaXogY29uIGNvbHVtbmFzIG5vbWJyYWRhcyBxdWUgZGFuIGNvdmFyaWFibGVzIGFkaWNpb25hbGVzIHBhcmEgbGFzIG1lZGlhcyBkZSBsb3MgcHJvY2Vzb3MgbGF0ZW50ZXMuIFNpIGVzIE5VTEwsIG5vIHNlIHV0aWxpemFuIGNvdmFyaWFibGVzIGFkaWNpb25hbGVzLg0KDQpgaHlwZXI6YCBVbmEgbGlzdGEgY29uIG5vbWJyZSBxdWUgZXNwZWNpZmljYSBsb3MgaGlwZXJwYXLDoW1ldHJvcw0KDQpgY292YXJpYWJsZXNgOiBNYXRyaXogY29uIGNvbHVtbmFzIG5vbWJyYWRhcyBxdWUgZGFuIGxhcyBjb3ZhcmlhYmxlcyByZXF1ZXJpZGFzIHBhcmEgbG9zIG1vZGVsb3MgZGUgcGFyw6FtZXRyb3MgZGUgR0VWLg0KDQpgcHJvcDpgVW5hIGxpc3RhIGNvbiBub21icmUgcXVlIGVzcGVjaWZpY2EgbG9zIHRhbWHDsW9zIGRlIHNhbHRvIGN1YW5kbyBzZSBuZWNlc2l0YSB1biBtb3ZpbWllbnRvIGRlIE1ldHJvcG9saXMtSGFzdGluZ3MNCg0KYHN0YXJ0YDogVW5hIGxpc3RhIGNvbiBub21icmUgcXVlIHByb3BvcmNpb25hIGxvcyB2YWxvcmVzIGluaWNpYWxlcw0KDQpgbjpgIExhIGxvbmdpdHVkIGVmZWN0aXZhIGRlIGxhIGNhZGVuYSBkZSBNYXJrb3Ygc2ltdWxhZGEsIGVzIGRlY2lyLCB1bmEgdmV6IGRlc2NhcnRhZG8gZWwgcGVyw61vZG8gZGUgcXVlbWFkbyB5IGRlc3B1w6lzIGRlbCBhZGVsZ2F6YW1pZW50by4NCg0KYHRoaW46YCBVbiBuw7ptZXJvIGVudGVybyBxdWUgZXNwZWNpZmljYSBsYSBsb25naXR1ZCBkZSBhZGVsZ2F6YW1pZW50by4gRWwgdmFsb3IgcHJlZGV0ZXJtaW5hZG8gZXMgMSwgZXMgZGVjaXIsIHNpbiBhZGVsZ2F6YW1pZW50bw0KDQpgYnVybi5pbjpgIFVuIG7Dum1lcm8gZW50ZXJvIHF1ZSBlc3BlY2lmaWNhIGVsIHBlcsOtb2RvIGRlIHF1ZW1hZG8uIEVsIHZhbG9yIHByZWRldGVybWluYWRvIGVzIDAsIGVzIGRlY2lyLCBzaW4gcXVlbWFkbw0KDQpgdXNlLmxvZy5saW5rOmAgVW4gZW50ZXJvLiDCv0RlYmVyw61hIHV0aWxpemFyc2UgdW5hIGZ1bmNpw7NuIGRlIGxpZ2EgbG9nYXLDrXRtaWNvIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIGxhIGVzY2FsYSBHRVYsIGVzIGRlY2lyLCBzdXBvbmllbmRvIHF1ZSBsb3MgcGFyw6FtZXRyb3MgZGUgbGEgZXNjYWxhIEdFViBzZSBleHRyYWVuIGRlIHVuIHByb2Nlc28gbG9nYXLDrXRtaWNvIG5vcm1hbCBlbiBsdWdhciBkZSB1biBwcm9jZXNvIGdhdXNzaWFubz8NCg0KDQoNCioqRGV0YWxsZXMqKg0KDQpFc3RhIGZ1bmNpw7NuIGdlbmVyYSB1bmEgY2FkZW5hIGRlIE1hcmtvdiBhIHBhcnRpciBkZWwgc2lndWllbnRlIG1vZGVsby4gUGFyYSBjYWRhICR4IFxpbiBSX2QkLCBzdXBvbmdhIHF1ZSAkWSAoeCkkIGVzIEdFViBkaXN0cmlidWlkbyBjdXlvcyBwYXLDoW1ldHJvcyAkXHvCtSAoeCk7IM+DKHgpOyDOviAoeClcfSQgdmFyw61hbiBzdWF2ZW1lbnRlIHBhcmEgJHggXGluIFJeZCQgZGUgYWN1ZXJkbyBjb24gdW4gcHJvY2VzbyBlc3RvY8Ohc3RpY28gJFMgKHgpJC4gU3Vwb25lbW9zIHF1ZSBsb3MgcHJvY2Vzb3MgcGFyYSBjYWRhIHBhcsOhbWV0cm8gZGUgR0VWIHNvbiBwcm9jZXNvcyBnYXVzc2lhbm9zIG11dHVhbWVudGUgaW5kZXBlbmRpZW50ZXMuIFBvciBlamVtcGxvLCB0b21hbW9zIGNvbW8gcGFyw6FtZXRybyBkZSB1YmljYWNpw7NuICTCtSAoeCkkDQoNCiQkDQpcbXUoeCk9Zl97XG11KHgpfVxsZWZ0KHggOyBcYmV0YV97XG11fVxyaWdodCkrU197XG11fVxsZWZ0KHggOyBcYWxwaGFfe1xtdX0sIFxsYW1iZGFfe1xtdX0sIFxrYXBwYV97XG11fVxyaWdodCkNCiQkDQoNCmRvbmRlICRmX8K1JCBlcyB1bmEgZnVuY2nDs24gZGV0ZXJtaW5pc3RhIHF1ZSBkZXBlbmRlIGRlIGxvcyBwYXLDoW1ldHJvcyBkZSByZWdyZXNpw7NuICTOsl/CtSQsIHkgJFNfwrUkIGVzIHVuIHByb2Nlc28gZ2F1c3NpYW5vIGVzdGFjaW9uYXJpbyBkZSBtZWRpYSBjZXJvIGNvbiB1bmEgZnVuY2nDs24gZGUgY292YXJpYW56YSBwcmVzY3JpdGEgY29uIHVtYnJhbCAkzrFfwrUkLCByYW5nbyAkzrtfwrUkIHkgcGFyw6FtZXRyb3MgZGUgZm9ybWEgJM66X8K1JC4gU2UgdXRpbGl6YW4gZm9ybXVsYWNpb25lcyBzaW1pbGFyZXMgcGFyYSBsb3MgcGFyw6FtZXRyb3MgZGUgZXNjYWxhICTPgyAoeCkkIHkgZm9ybWEgJM6+ICh4KSQuIEx1ZWdvLCBjb25kaWNpb25hZG8gYSBsb3MgdmFsb3JlcyBkZSBsb3MgdHJlcyBwcm9jZXNvcyBnYXVzc2lhbm9zIGVuIGxvcyBzaXRpb3MgJCh4XzEsLi4uLCB4X0spJCwgc2Ugc3Vwb25lIHF1ZSBsb3MgbcOheGltb3Mgc2lndWVuIGRpc3RyaWJ1Y2lvbmVzIEdFVg0KDQokJA0KWV97aX1cbGVmdCh4X3tqfVxyaWdodCkgXG1pZFxsZWZ0XHtcbXVcbGVmdCh4X3tqfVxyaWdodCksIFxzaWdtYVxsZWZ0KHhfe2p9XHJpZ2h0KSwgXHhpXGxlZnQoeF97an1ccmlnaHQpXHJpZ2h0XH0gXHNpbSBcb3BlcmF0b3JuYW1le0dFVn1cbGVmdFx7XG11XGxlZnQoeF97an1ccmlnaHQpLCBcc2lnbWFcbGVmdCh4X3tqfVxyaWdodCksIFx4aVxsZWZ0KHhfe2p9XHJpZ2h0KVxyaWdodFx9LA0KJCQNCg0KaW5kZXBlbmRpZW50ZW1lbnRlIHBhcmEgY2FkYSB1YmljYWNpw7NuICQoeF8xLC4uLiwgeF9LKSQuDQoNClNlIGRlYmUgZGVmaW5pciB1bmEgZGVuc2lkYWQgYSBwcmlvcmkgY29uanVudGEgcGFyYSBsb3MgdW1icmFsZXMsIHJhbmdvcyB5IHBhcsOhbWV0cm9zIGRlIGZvcm1hcyBkZSBsYXMgZnVuY2lvbmVzIGRlIGNvdmFyaWFuemEsIGFzw60gY29tbyBwYXJhIGxvcyBwYXLDoW1ldHJvcyBkZSByZWdyZXNpw7NuICTOsl/CtSQsICTOsl/PgyQgeSAkzrJfzr4kLiBTaWVtcHJlIHF1ZSBzZWEgcG9zaWJsZSwgc2UgdXRpbGl6YW4gYSBwcmlvcmkgY29uanVnYWRvcywgdG9tYW5kbyBkaXN0cmlidWNpb25lcyBHYW1tYSBpbnZlcnNhIGluZGVwZW5kaWVudGUgeSBub3JtYWwgbXVsdGl2YXJpYW50ZSBwYXJhIGxvcyB1bWJyYWxlcyB5IGxvcyBwYXLDoW1ldHJvcyBkZSByZWdyZXNpw7NuLiBObyBleGlzdGUgdW4gY29uanVnYWRvIGEgcHJpb3JpIHBhcmEgJM67JCB5ICTOuiQsIHBvciBsbyBxdWUgc2Ugc3Vwb25lIHVuYSBkaXN0cmlidWNpw7NuIEdhbW1hLg0KDQpFbiBjb25zZWN1ZW5jaWEsIGBoeXBlcmAgZXMgdW5hIGxpc3RhIGNvbiBub21icmUgY29uIGNvbXBvbmVudGVzIGNvbiBub21icmUuDQoNCg0KKyB1bWJyYWxlcyhzaWxscyk6IFVuYSBsaXN0YSBjb24gdHJlcyBjb21wb25lbnRlcyBkZW5vbWluYWRvcyAibG9jIiwgImVzY2FsYSIgeSAiZm9ybWEiLCBjYWRhIHVubyBkZSBlbGxvcyBlcyB1biB2ZWN0b3IgZGUgMiBsb25naXR1ZGVzIHF1ZSBlc3BlY2lmaWNhIGxhIGZvcm1hIHkgbGEgZXNjYWxhIGRlIGxhIGRpc3RyaWJ1Y2nDs24gYSBwcmlvcmkgR2FtbWEgaW52ZXJzYSBwYXJhIGVsIHBhcsOhbWV0cm8gdW1icmFsIGRlIGxhcyBmdW5jaW9uZXMgZGUgY292YXJpYW56YTsNCg0KKyByYW5nb3MocmFuZ2VzKTogVW5hIGxpc3RhIGNvbiB0cmVzIGNvbXBvbmVudGVzIGRlbm9taW5hZG9zICJsb2MiLCAiZXNjYWxhIiB5ICJmb3JtYSIsIGNhZGEgdW5vIGRlIGVsbG9zIGVzIHVuIHZlY3RvciBkZSAyIGxvbmdpdHVkZXMgcXVlIGVzcGVjaWZpY2EgbGEgZm9ybWEgeSBsYSBlc2NhbGEgZGUgbGEgZGlzdHJpYnVjacOzbiBhIHByaW9yaSBHYW1tYSBwYXJhIGVsIHBhcsOhbWV0cm8gZGUgcmFuZ28gZGUgbGFzIGZ1bmNpb25lcyBkZSBjb3ZhcmlhbnphLg0KDQorIHN1YXZpemEoc21vb3Rocyk6IFVuYSBsaXN0YSBjb24gdHJlcyBjb21wb25lbnRlcyBkZW5vbWluYWRvcyAibG9jIiwgImVzY2FsYSIgeSAiZm9ybWEiLCBjYWRhIHVubyBkZSBlbGxvcyBlcyB1biB2ZWN0b3IgZGUgMiBsb25naXR1ZGVzIHF1ZSBlc3BlY2lmaWNhIGxhIGZvcm1hIHkgbGEgZXNjYWxhIGRlIGxhIGRpc3RyaWJ1Y2nDs24gcHJldmlhIEdhbW1hIHBhcmEgZWwgcGFyw6FtZXRybyBkZSBmb3JtYSBkZSBsYXMgZnVuY2lvbmVzIGRlIGNvdmFyaWFuemE7DQoNCisgYmV0YU1lYW46IFVuYSBsaXN0YSBjb24gdHJlcyBjb21wb25lbnRlcyBkZW5vbWluYWRvcyAibG9jIiwgImVzY2FsYSIgeSAiZm9ybWEiLCBjYWRhIHVubyBkZSBlbGxvcyBlcyB1biB2ZWN0b3IgcXVlIGVzcGVjaWZpY2EgZWwgdmVjdG9yIG1lZGlvIGRlIGxhIGRpc3RyaWJ1Y2nDs24gcHJldmlhIG5vcm1hbCBtdWx0aXZhcmlhbnRlIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIHJlZ3Jlc2nDs247DQoNCisgYmV0YUljb3Y6IFVuYSBsaXN0YSBjb24gdHJlcyBjb21wb25lbnRlcyBkZW5vbWluYWRvcyAibG9jIiwgImVzY2FsYSIgeSAiZm9ybWEiLCBjYWRhIHVubyBkZSBlbGxvcywgZXMgdW5hIG1hdHJpeiBxdWUgZXNwZWNpZmljYSBsYSBpbnZlcnNhIGRlIGxhIG1hdHJpeiBkZSBjb3ZhcmlhbnphIGRlIGxhIGRpc3RyaWJ1Y2nDs24gcHJldmlhIG5vcm1hbCBtdWx0aXZhcmlhbnRlIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIHJlZ3Jlc2nDs24uDQoNCkNvbW8gbm8gZXhpc3RlIHVuYSBhIHByaW9yaSBjb25qdWdhZG8gcGFyYSBsb3MgcGFyw6FtZXRyb3MgZGUgR0VWIHkgbG9zIHBhcsOhbWV0cm9zIGRlIHJhbmdvIHkgZm9ybWEgZGUgbGFzIGZ1bmNpb25lcyBkZSBjb3ZhcmlhbnphLCBzZSBuZWNlc2l0YW4gbG9zIHBhc29zIGRlIE1ldHJvcG9saXMtSGFzdGluZ3MuIExhcyBwcm9wdWVzdGFzICTOuF97cHJvcH0kIHNlIGV4dHJhZW4gZGUgdW5hIGRlbnNpZGFkIGRlIHByb3B1ZXN0YSAgJHEowrcgfCDOuF97Y3VyfSwgcykkIGRvbmRlICTOuF97Y3VyfSQgZXMgZWwgZXN0YWRvIGFjdHVhbCBkZWwgcGFyw6FtZXRybyB5IHMgZXMgdW4gcGFyw6FtZXRybyBkZSBsYSBkZW5zaWRhZCBkZSBwcm9wdWVzdGEgYSBkZWZpbmlyLiBFc3RhcyBwcm9wdWVzdGFzIGVzdMOhbiBpbXB1bHNhZGFzIHBvciBwcm9wLCBxdWUgZXMgdW5hIGxpc3RhIGNvbiB0cmVzIGNvbXBvbmVudGVzIG5vbWJyYWRvcw0KDQorIGdldjogVW4gdmVjdG9yIGRlIGxvbmdpdHVkIDMgcXVlIGVzcGVjaWZpY2EgbGFzIGRlc3ZpYWNpb25lcyBlc3TDoW5kYXIgZGUgbGFzIGRpc3RyaWJ1Y2lvbmVzIHByb3B1ZXN0YXMuIEVzdG9zIHNlIHRvbWFuIGNvbW8gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIEdFViBkZSB1YmljYWNpw7NuIHkgZm9ybWEgeSB1bmEgZGlzdHJpYnVjacOzbiBsb2dhcsOtdG1pY2Egbm9ybWFsIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIEdFViBkZSBlc2NhbGE7DQoNCisgcmFuZ29zKHJhbmdlcyk6IFVuIHZlY3RvciBkZSBsb25naXR1ZCAzIHF1ZSBlc3BlY2lmaWNhIGxvcyB0YW1hw7FvcyBkZSBzYWx0byBwYXJhIGxvcyBwYXLDoW1ldHJvcyBkZSByYW5nbyBkZSBsYXMgZnVuY2lvbmVzIGRlIGNvdmFyaWFuemEgLSAkcSAowrcgfCDOuF97Y3VyfSwgcykkIGVzIGxhIGRlbnNpZGFkIGxvZ2Fyw610bWljYSBub3JtYWwgY29uIG1lZGlhICTOuF97Y3VyfSQgIHkgZGVzdmlhY2nDs24gZXN0w6FuZGFyIHMgYW1iYXMgZW4gbGEgZXNjYWxhIGxvZ2Fyw610bWljYTsNCg0KKyBzdWF2aXphKHNtb290aCkgVW4gdmVjdG9yIGRlIGxvbmdpdHVkIDMgcXVlIGVzcGVjaWZpY2EgbG9zIHRhbWHDsW9zIGRlIHNhbHRvIHBhcmEgbG9zIHBhcsOhbWV0cm9zIGRlIGZvcm1hIGRlIGxhcyBmdW5jaW9uZXMgZGUgY292YXJpYW56YSAtICRxICjCtyB8IM64X3tjdXJ9LCBzKSQgZXMgbGEgZGVuc2lkYWQgbG9nYXLDrXRtaWNhIG5vcm1hbCBjb24gbWVkaWEgJM64X3tjdXJ9JCB5IGRlc3ZpYWNpw7NuIGVzdMOhbmRhciBzIGFtYmFzIGVuIGxhIGVzY2FsYSBsb2dhcsOtdG1pY2EuDQoNClNpIHVubyBxdWllcmUgbWFudGVuZXIgZmlqbyB1biBwYXLDoW1ldHJvLCBlc3RvIHNlIHB1ZWRlIGhhY2VyIGVzdGFibGVjaWVuZG8gdW4gdGFtYcOxbyBkZSBzYWx0byBudWxvLCBlbnRvbmNlcyBlbCBwYXLDoW1ldHJvIHNlIG1hbnRlbmRyw6EgZmlqbyBlbiBzdSB2YWxvciBpbmljaWFsLg0KDQpGaW5hbG1lbnRlLCBlbCBgc3RhcmAgZGViZSBzZXIgdW5hIGxpc3RhIGNvbiBub21icmUgY29uIDQgY29tcG9uZW50ZXMgY29uIG5vbWJyZQ0KDQorIHVtYnJhbGVzKHNpbGwpIFVuIHZlY3RvciBkZSBsb25naXR1ZCAzIHF1ZSBlc3BlY2lmaWNhIGxvcyB2YWxvcmVzIGluaWNpYWxlcyBwYXJhIGVsIHVtYnJhbCBkZSBsYXMgZnVuY2lvbmVzIGRlIGNvdmFyaWFuemE7DQoNCisgcmFuZ29zKHJhbmdlcykgVW4gdmVjdG9yIGRlIGxvbmdpdHVkIDMgcXVlIGVzcGVjaWZpY2EgbG9zIHZhbG9yZXMgaW5pY2lhbGVzIHBhcmEgZWwgcmFuZ28gZGUgbGFzIGZ1bmNpb25lcyBkZSBjb3ZhcmlhbnphOw0KDQorIHN1YXZpemEoc21vb3RoKSBVbiB2ZWN0b3IgZGUgbG9uZ2l0dWQgMyBxdWUgZXNwZWNpZmljYSBsb3MgdmFsb3JlcyBpbmljaWFsZXMgcGFyYSBsYSBmb3JtYSBkZSBsYXMgZnVuY2lvbmVzIGRlIGNvdmFyaWFuemE7DQoNCisgYmV0YSBVbmEgbGlzdGEgY29uIG5vbWJyZSBjb24gMyBjb21wb25lbnRlcyAibG9jIiwgImVzY2FsYSIgeSAiZm9ybWEiLCBjYWRhIHVubyBkZSBlbGxvcyBlcyB1biB2ZWN0b3IgbnVtw6lyaWNvIHF1ZSBlc3BlY2lmaWNhIGxvcyB2YWxvcmVzIGluaWNpYWxlcyBwYXJhIGxvcyBjb2VmaWNpZW50ZXMgZGUgcmVncmVzacOzbi4NCg0KDQpWYWxvcg0KVW5hIGxpc3RhDQoNCkFkdmVydGVuY2lhDQpFc3RhIGZ1bmNpw7NuIHB1ZWRlIGxsZXZhciBtdWNobyB0aWVtcG8geSBoYWNlIHVuIHVzbyBpbnRlbnNpdm8gZGUgbGFzIHJ1dGluYXMgQkxBUywgcG9yIGxvIHF1ZSBlcyAowqFtdWNobyEpIE3DoXMgcsOhcGlkYSBzaSB0aWVuZSB1biBCTEFTIG9wdGltaXphZG8uIExvcyB2YWxvcmVzIGluaWNpYWxlcyBudW5jYSBzZSBhbG1hY2VuYXLDoW4gZW4gbGEgY2FkZW5hIGRlIE1hcmtvdiBnZW5lcmFkYSBpbmNsdXNvIGN1YW5kbyBgYnVybi5pbiA9IDAuYA0KDQojIyBNb2RlbG8NCg0KUmVjb3JkYW5kbyBxdWUgDQoNCiQkDQpZX3tpfVxsZWZ0KHhfe2p9XHJpZ2h0KSBcbWlkXGxlZnRce1xtdVxsZWZ0KHhfe2p9XHJpZ2h0KSwgXHNpZ21hXGxlZnQoeF97an1ccmlnaHQpLCBceGlcbGVmdCh4X3tqfVxyaWdodClccmlnaHRcfSBcc2ltIFxvcGVyYXRvcm5hbWV7R0VWfVxsZWZ0XHtcbXVcbGVmdCh4X3tqfVxyaWdodCksIFxzaWdtYVxsZWZ0KHhfe2p9XHJpZ2h0KSwgXHhpXGxlZnQoeF97an1ccmlnaHQpXHJpZ2h0XH0sDQokJA0KDQppbmRlcGVuZGllbnRlbWVudGUgcGFyYSBjYWRhIHViaWNhY2nDs24gJCh4XzEsLi4uLCB4X0spJC4NCg0KZG9uZGUgDQoNCiQkDQpcbXUoeCk9Zl97XG11KHgpfVxsZWZ0KHggOyBcYmV0YV97XG11fVxyaWdodCkrU197XG11fVxsZWZ0KHggOyBcYWxwaGFfe1xtdX0sIFxsYW1iZGFfe1xtdX0sIFxrYXBwYV97XG11fVxyaWdodCkNCiQkDQoNCiQkDQpcc2lnbWEoeCk9Zl97XHNpZ21hKHgpfVxsZWZ0KHggOyBcYmV0YV97XHNpZ21hfVxyaWdodCkrU197XHNpZ21hfVxsZWZ0KHggOyBcYWxwaGFfe1xzaWdtYX0sIFxsYW1iZGFfe1xzaWdtYX0sIFxrYXBwYV97XG11fVxyaWdodCkNCiQkDQoNCiQkDQpceGkoeCk9Zl97XHhpKHgpfVxsZWZ0KHggOyBcYmV0YV97XHhpfVxyaWdodCkrU197XHhpfVxsZWZ0KHggOyBcYWxwaGFfe1x4aX0sIFxsYW1iZGFfe1x4aX0sIFxrYXBwYV97XHhpfVxyaWdodCkNCiQkDQoNCkFob3JhIGNvbmNlbnRyYW5kb25vcyBlbiAkXG11KHgpJCwgbm90ZSBxdWUgDQoNCiQkDQpcbXUoeCk9Zl97XG11KHgpfVxsZWZ0KHggOyBcYmV0YV97XG11fVxyaWdodCkrU197XG11fVxsZWZ0KHggOyBcYWxwaGFfe1xtdX0sIFxsYW1iZGFfe1xtdX0sIFxrYXBwYV97XG11fVxyaWdodCkNCiQkDQoNCmNvbmZvcm1lIGEgDQoNCioqQmFuZXJqZWUsIFMuLCBDYXJsaW4sIEIuIFAuLCBhbmQgR2VsZmFuZCwgQS4gRS4gKDIwMDQpLiBIaWVyYXJjaGljYWwgTW9kZWxpbmcgYW5kIEFuYWx5c2lzIGZvciBTcGF0aWFsIERhdGEuIENoYXBtYW4gJiBIYWxsL0NSQywgTmV3IFlvcmsuKioNCg0KKipDYXNzb24sIEUuIGFuZCBDb2xlcywgUy4gKDE5OTkpIFNwYXRpYWwgcmVncmVzc2lvbiBtb2RlbHMgZm9yIGV4dHJlbWVzLiBFeHRyZW1lcyAxLDQ0OeKAkzQ2OC4qKg0KDQoqKkNvb2xleSwgRC4sIE55Y2hrYSwgRC4gYW5kIE5hdmVhdSwgUC4gKDIwMDcpIEJheWVzaWFuIHNwYXRpYWwgbW9kZWxsaW5nIG9mIGV4dHJlbWUgcHJlY2lwaXRhdGlvbioqDQoNCioqcmV0dXJuIGxldmVscyBKb3VybmFsIG9mIHRoZSBBbWVyaWNhbiBTdGF0aXN0aWNhbCBBc3NvY2lhdGlvbiAxMDI6NDc5LCA4MjTigJM4NDAuKioNCg0KKipEYXZpc29uLCBBLkMuLCBQYWRvYW4sIFMuQS4gYW5kIFJpYmF0ZXQsIE0uIFN0YXRpc3RpY2FsIE1vZGVsbGluZyBvZiBTcGF0aWFsIEV4dHJlbWVzLiBTdWJtaXR0ZWQuKioNCg0Kc3VndWllcmVuIHF1ZSBsb3MgcGFyw6FtZXRyb3MgZGUgdW1icmFsLCByYW5nbyB5IGZvcm1hLg0KDQokJA0KXGFscGhhLCBcbGFtYmRhLCBca2FwcGEgXHNpbSBwKFxhbHBoYSwgXGxhbWJkYSwgXGthcHBhKSANCiQkDQoNCmVuIHBhcnRpY3VsYXIgZWwgdW1icmFsDQoNCiQkDQpcYWxwaGEgXHNpbSBJRyhhXzEsIGJfMSkgDQokJA0KZWwgcmFuZ28NCg0KJCQNClxsYW1iZGEsIFxrYXBwYSBcc2ltIEcoYV97MiwzfSwgYl97MiwzfSkgDQokJA0KYWRlbWFzDQoNCiQkDQpcYmV0YSBcc2ltIE4oXGJvbGRzeW1ib2x7XG11fSxcYm9sZHN5bWJvbHtcU2lnbWF9KQ0KJCQNCiMjIEFwbGljYWNpw7NuDQoNCklsdXN0cmFtb3MgbGEgZGlzY3VzacOzbiBhbnRlcmlvciB1c2FuZG8gbG9zIGRhdG9zIGRlIHByZWNpcGl0YWNpw7NuIG3DoXhpbWEgYW51YWwgZGVzY3JpdG9zLiBQb3IgbG8gcXVlIGFqdXN0YW1vcyBsYSBkaXN0cmlidWNpw7NuIGRlIHZhbG9yZXMgZXh0cmVtb3MgZ2VuZXJhbGl6YWRvcywgdXRpbGl6YW5kbyBwYXLDoW1ldHJvcyBkZXNjcml0b3MgcG9yIGxhcyBzdXBlcmZpY2llcyBkZSB0ZW5kZW5jaWENCg0KJCQNClxiZWdpbnthcnJheX17bH0NClxldGEoeCk9XGJldGFfezAsIFxldGF9K1xiZXRhX3sxLCBcZXRhfSBcb3BlcmF0b3JuYW1le2xvbn0oeCkrXGJldGFfezIsIFxldGF9IFxvcGVyYXRvcm5hbWV7bGF0fSh4KSwgXFwNClx0YXUoeCk9XGJldGFfezAsIFx0YXV9K1xiZXRhX3sxLCBcdGF1fSBcb3BlcmF0b3JuYW1le2xvbn0oeCkrXGJldGFfezIsIFx0YXV9IFxvcGVyYXRvcm5hbWV7bGF0fSh4KSwgXFwNClx4aSh4KT1cYmV0YV97MCwgXHhpfQ0KXGVuZHthcnJheX0NCiQkDQpkb25kZSBsb24gKHgpIHkgbGF0ICh4KSBzb24gbGEgbG9uZ2l0dWQgeSBsYXRpdHVkIGRlIGxhcyBlc3RhY2lvbmVzIGVuIGxhcyBxdWUgc2Ugb2JzZXJ2YW4gbG9zIGRhdG9zLiBMYSBlc3RydWN0dXJhIG1hcmdpbmFsIGRlIGxhcyBlY3VhY2lvbmVzIGFudGVyaW9yZXMgc2UgZWxpZ2nDsyB1dGlsaXphbmRvIGVsIENMSUMgeSBsb3MgdmFsb3JlcyBkZSB2ZXJvc2ltaWxpdHVkIG9idGVuaWRvcyBhbCBhanVzdGFyIHVuYSBhbXBsaWEgZ2FtYSBkZSBtb2RlbG9zIHBsYXVzaWJsZXMuIA0KDQpSZWN1ZXJkZSBxdWUgZWwgQ0xJQyBlczoNCg0KKExhIHNlbGVjY2nDs24gZGVsIG1vZGVsbyBzZSBlZmVjdMO6YSBtaW5pbWl6YW5kbyBlbCBjcml0ZXJpbyBkZSBpbmZvcm1hY2nDs24gZGUgdmVyb3NpbWlsaXR1ZCBjb21wdWVzdGEsIHF1ZSB0aWVuZSBwcm9waWVkYWRlcyBhbsOhbG9nYXMgYSBsYXMgZGUgQUlDIHkgVElDKQ0KDQokJA0KQ0xJQyA9IC0yIFxlbGxfe3B9KFxoYXR7XHZhcnRoZXRhfSkrMiBcb3BlcmF0b3JuYW1le3RyfVxsZWZ0XHtKXnstMX0oXGhhdHtcdmFydGhldGF9KSBLKFxoYXR7XHZhcnRoZXRhfSlccmlnaHRcfQ0KJCQNCg0KDQojIyBjb2RlDQoNCmBgYHtyLCBjYWNoZT1UUlVFfQ0KYmcgPC0gYmcgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKFJhaW4gPiAzMCkNCg0KYmcgJT4lIA0KICBwbG90X2RlbnNpdHkoeCA9IFJhaW4sDQogICAgICAgICAgICAgICB0aXRsZSA9ICIoMjAxOC0yMDIwKSBiYXNpYyBkZW5zaXR5IHBsb3QgZ2VuZXJhbCBvZiBjdW1fcmFpbiIsDQogICAgICAgICAgICAgICBmaWxsID0gInNhbG1vbjEiKQ0KDQp0YWJsZShiZyRTdGF0aW9uKQ0KbGlicmFyeShTcGF0aWFsRXh0cmVtZXMpDQojIyBOb3QgcnVuOg0KIyMgR2VuZXJhdGUgcmVhbGl6YXRpb25zIGZyb20gdGhlIG1vZGVsDQpuLnNpdGUgPC0gNCAjIG51bWVybyBkZSBzaXRpb3MgbXVlc3RyZWFkb3MNCg0Kbi5vYnMgIDwtIDExICMgbnVtZXJvIGRlIG9ic2VydmFjaW9uZXMgdG9tYWRhIGVuIGNhZGEgc2l0aW8gbXVlc3RyZWFkbw0KDQpjb29yZCAgPC0gYmcgJT4lICAgICAgICAgICAgICAgICAgICAjIGNyZWFtb3MgbGEgbWF0cml4IGRlIGNvb3JkZW5hZGFzDQogIHNlbGVjdChMb25naXR1ZCwgTGF0aXR1ZCkgJT4lICAgICAgICMgZXN0YSBtYXRyaXggZGUgY29vcmRlbmFkYXMgc29sbyBpbmNsdXllIGVsDQogIHVuaXF1ZSgpICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbnVtZXJvIGRlIHNpdGlvcyBkb25kZSBzZSBtdWVzdHJlbw0KDQpjb29yZCAgPC0gY2JpbmQobG9uID0gY29vcmQkTG9uZ2l0dWQsIGxhdCA9IGNvb3JkJExhdGl0dWQpICMgbWF0cml4IGRlIGNvb3JkZW5hZGFzDQojIHNpbiBtZWRpY2lvbmVzIHJlcGV0aWRhcw0KIyBjbGFzcyhjb29yZCkNCiMgY29vcmQgPC0gY2JpbmQobG9uID0gcnVuaWYobi5zaXRlLCAtMTAsIDEwKSwgbGF0ID0gcnVuaWYobi5zaXRlLCAtMTAgLCAxMCkpDQoNCiMgY3JlYW1vcyB1biBwcm9jZXNvIGdhdXNzaWFubyBwYXJhIGNhZGEgcGFyYW1ldHJvICBkZSBsYSBHRVYsIGVzdGEgcGFydGUgc2UgZGVqYQ0KIyBhIGVsZWNjacOzbiBkZWwgYXV0b3IgZWxlZ2lybG8uDQoNCmdwLmxvYyAgIDwtIFNwYXRpYWxFeHRyZW1lczo6cmdwKDEsIGNvb3JkLCAicG93ZXhwIiwgc2lsbCA9IDAuMDEsIHJhbmdlID0gMTAsIHNtb290aCA9IDEpDQpncC5zY2FsZSA8LSBTcGF0aWFsRXh0cmVtZXM6OnJncCgxLCBjb29yZCwgInBvd2V4cCIsIHNpbGwgPSAwLjAwMSwgcmFuZ2UgPSAxNSwgc21vb3RoID0gMSkNCmdwLnNoYXBlIDwtIFNwYXRpYWxFeHRyZW1lczo6cmdwKDEsIGNvb3JkLCAicG93ZXhwIiwgc2lsbCA9IDAuMDAxLCByYW5nZSA9IDIwLCBzbW9vdGggPSAxKQ0KDQoNCiMgbG9jcyAgIDwtIDI2ICsgMC41ICogY29vcmRbLCJsb24iXSArIGdwLmxvYw0KIyBzY2FsZXMgPC0gMTAgKyAwLjIgKiBjb29yZFssImxhdCJdICsgZ3Auc2NhbGUNCiMgc2hhcGVzIDwtIDAuMTUgKyBncC5zaGFwZQ0KDQoNCiMgRXN0aW1hdGVkIFBhcmFtZXRlcnM6DQojICAgICAgICAgeGkgICAgICAgICBtdSAgICAgICBiZXRhIA0KIyAgMC4zOTQ0NjQxIDM0LjEzODc0NzIgIDQuNzg4MjcxNCANCg0KZGF0YSA8LSBtYXRyaXgoTkEsIG4ub2JzLCBuLnNpdGUpDQojIA0KIyBmb3IgKGkgaW4gMTpuLnNpdGUpDQojICAgZGF0YVssaV0gPC0gU3BhdGlhbEV4dHJlbWVzOjpyZ2V2KG4ub2JzLCBsb2NzW2ldLCBzY2FsZXNbaV0sIHNoYXBlc1tpXSkNCmRpbShiZykNCnRhYmxlKGJnJFN0YXRpb24pDQoNCmRhdGFbLDFdICA8LWJnICU+JSANCiAgZHBseXI6OnNlbGVjdChSYWluLCBTdGF0aW9uKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoU3RhdGlvbiA9PSAiQXJyaWFnYSIpICU+JSANCiAgIyBzbGljZSgxOjUpICU+JSANCiAgZHBseXI6OnNlbGVjdChSYWluKSAlPiUgDQogIGRwbHlyOjphcnJhbmdlKC1SYWluKSAlPiUgDQogIHNsaWNlKDE6MTEpICU+JSANCiAgYXMubWF0cml4KCkNCmRhdGFbLDJdICA8LWJnICU+JSANCiAgZHBseXI6OnNlbGVjdChSYWluLCBTdGF0aW9uKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoU3RhdGlvbiA9PSAiQ29taXRhbiIpICU+JSANCiAgIyBzbGljZSgxOjUpICU+JSANCiAgc2VsZWN0KFJhaW4pICU+JSANCiAgYXJyYW5nZSgtUmFpbikgJT4lIHNsaWNlKDE6MTEpICU+JSANCiAgYXMubWF0cml4KCkNCiMgZGF0YVssM10gIDwtIGJnICU+JSANCiMgICBkcGx5cjo6c2VsZWN0KGN1bV9yYWluLCBTdGF0aW9uKSAlPiUgDQojICAgZHBseXI6OmZpbHRlcihTdGF0aW9uID09ICJzY2RsYyIpICU+JSANCiMgICAjIHNsaWNlKDE6NSkgJT4lIA0KIyAgIHNlbGVjdChjdW1fcmFpbikgJT4lIA0KIyAgIGFycmFuZ2UoLWN1bV9yYWluKSAlPiUgIyBzbGljZSgxOjYxKSAlPiUgDQojICAgYXMubWF0cml4KCkNCmRhdGFbLDNdICA8LSBiZyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoUmFpbiwgU3RhdGlvbikgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKFN0YXRpb24gPT0gIlRhcGFjaHVsYSIpICU+JSANCiAgIyBzbGljZSgxOjUpICU+JSANCiAgc2VsZWN0KFJhaW4pICU+JSANCiAgYXJyYW5nZSgtUmFpbikgJT4lIHNsaWNlKDE6MTEpICU+JSANCiAgYXMubWF0cml4KCkNCmRhdGFbLDRdICA8LSBiZyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoUmFpbiwgU3RhdGlvbikgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKFN0YXRpb24gPT0gIlR1eHRsYSIpICU+JSANCiAgIyBzbGljZSgxOjUpICU+JSANCiAgc2VsZWN0KFJhaW4pICU+JSANCiAgYXJyYW5nZSgtUmFpbikgJT4lICBzbGljZSgxOjExKSAlPiUgDQogIGFzLm1hdHJpeCgpDQoNCiMgYjIwMThbYjIwMTgkU3RhdGlvbiA9PSAiQXJyaWFnYSIsIDNdDQojIGRhdGFbLDVdIDwtIGIyMDE4W2IyMDE4JFN0YXRpb24gPT0gInR1eHRsYWciLCAzXQ0KIyBkYXRhWywxXSAgPC0gYjIwMThbMToxMCwzXQ0KDQojIGxvYy5mb3JtICAgPC0geSB+IGxvbg0KIyBzY2FsZS5mb3JtIDwtIHkgfiBsYXQNCiMgc2hhcGUuZm9ybSA8LSB5IH4gMQ0KDQpsb2MuZm9ybSAgIDwtIHkgfiAxDQpzY2FsZS5mb3JtIDwtIHkgfiAxDQpzaGFwZS5mb3JtIDwtIHkgfiAxDQoNCmh5cGVyIDwtIGxpc3QoKQ0KaHlwZXIkc2lsbHMgICAgIDwtIGxpc3QobG9jID0gYygxLDgpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gYygxLDEpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gYygxLDAuMDIpKQ0KaHlwZXIkcmFuZ2VzICAgIDwtIGxpc3QobG9jID0gYygyLDIwKSwgDQogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IGMoMSw1KSwgDQogICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IGMoMSwgMTApKQ0KaHlwZXIkc21vb3RocyAgIDwtIGxpc3QobG9jID0gYygxLDEvMyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBjKDEsMS8zKSwgDQogICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IGMoMSwgMS8zKSkNCmh5cGVyJGJldGFNZWFucyA8LSBsaXN0KGxvYyA9IDksIA0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSA2LCANCiAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMikNCmh5cGVyJGJldGFJY292ICA8LSBsaXN0KGxvYyA9ICAgc29sdmUoZGlhZyhjKDEwKSwgMSwgMSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBzb2x2ZShkaWFnKGMoMTApLCAxLCAxKSksDQogICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IHNvbHZlKGRpYWcoYygwLjEzKSwgMSwgMSkpKQ0KIyMgV2Ugd2lsbCB1c2UgYW4gZXhwb25lbnRpYWwgY292YXJpYW5jZSBmdW5jdGlvbiBzbyB0aGUganVtcCBzaXplcyBmb3INCiMjIHRoZSBzaGFwZSBwYXJhbWV0ZXIgb2YgdGhlIGNvdmFyaWFuY2UgZnVuY3Rpb24gYXJlIG51bGwuDQoNCnByb3AgPC0gbGlzdChnZXYgPSBjKDEuMiwgMC4wOCwgMC4wOCksIHJhbmdlcyA9IGMoMC43LCAwLjgsIDAuNyksIHNtb290aHMgPSBjKDAsMCwwKSkNCg0Kc3RhcnQgPC0gbGlzdChzaWxscyA9IGMoNCwgLjM2LCAwLjAwOSksIA0KICAgICAgICAgICAgICByYW5nZXMgPSBjKDI0LCAxNywgMTYpLCANCiAgICAgICAgICAgICAgc21vb3Rocz0gYygxLCAxLCAxKSwgDQogICAgICAgICAgICAgIGJldGEgPSBsaXN0KGxvYyA9IGMoMjQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBjKDcuMzEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IGMoMC41NCkpKQ0KDQojIEVzdGltYXRlZCBQYXJhbWV0ZXJzOg0KIyAgIHhpICAgICAgICAgbXUgICAgICAgYmV0YSANCiMgMC41MzA0OTg4IDM3LjMyMjEwOTAgIDcuNDA0MzQxNyANCg0KbWMxIDwtIGxhdGVudChkYXRhLCBjb29yZCwgDQogICAgICAgICAgICAgbG9jLmZvcm0gPSBsb2MuZm9ybSwgDQogICAgICAgICAgICAgc2NhbGUuZm9ybSA9IHNjYWxlLmZvcm0sDQogICAgICAgICAgICAgc2hhcGUuZm9ybSA9IHNoYXBlLmZvcm0sIA0KICAgICAgICAgICAgIGh5cGVyID0gaHlwZXIsIA0KICAgICAgICAgICAgIHByb3AgPSBwcm9wLCANCiAgICAgICAgICAgICBzdGFydCA9IHN0YXJ0LA0KICAgICAgICAgICAgIG4gPSAxMDAwMCwgDQogICAgICAgICAgICAgYnVybi5pbiA9IDUwMDAsIA0KICAgICAgICAgICAgIHRoaW4gPSAxNSkNCm1jMQ0KDQptYzIgPC0gbGF0ZW50KGRhdGEsIGNvb3JkLCANCiAgICAgICAgICAgICBsb2MuZm9ybSA9IGxvYy5mb3JtLCANCiAgICAgICAgICAgICBzY2FsZS5mb3JtID0gc2NhbGUuZm9ybSwNCiAgICAgICAgICAgICBzaGFwZS5mb3JtID0gc2hhcGUuZm9ybSwgDQogICAgICAgICAgICAgaHlwZXIgPSBoeXBlciwgDQogICAgICAgICAgICAgcHJvcCA9IHByb3AsIA0KICAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnQsDQogICAgICAgICAgICAgbiA9IDEwMDAwLCANCiAgICAgICAgICAgICBidXJuLmluID0gNTAwMCwgDQogICAgICAgICAgICAgdGhpbiA9IDE1KQ0KbWMyDQoNCm1jMyA8LSBsYXRlbnQoZGF0YSwgY29vcmQsIA0KICAgICAgICAgICAgIGxvYy5mb3JtID0gbG9jLmZvcm0sIA0KICAgICAgICAgICAgIHNjYWxlLmZvcm0gPSBzY2FsZS5mb3JtLA0KICAgICAgICAgICAgIHNoYXBlLmZvcm0gPSBzaGFwZS5mb3JtLCANCiAgICAgICAgICAgICBoeXBlciA9IGh5cGVyLCANCiAgICAgICAgICAgICBwcm9wID0gcHJvcCwgDQogICAgICAgICAgICAgc3RhcnQgPSBzdGFydCwNCiAgICAgICAgICAgICBuID0gMTAwMDAsIA0KICAgICAgICAgICAgIGJ1cm4uaW4gPSA1MDAwLCANCiAgICAgICAgICAgICB0aGluID0gMTUpDQptYzMNCiMjIEVuZChOb3QgcnVuKQ0KDQojIGEgPC0gc3VtbWFyeShtYykNCiMgDQojIGENCiMgaGVhZChtYyRjaGFpbi5sb2MpDQojIGhlYWQobWMkY2hhaW4uc2NhbGUpDQojIGhlYWQobWMkY2hhaW4uc2hhcGUpDQojIGhlYWQobWMkbG9jLmRzZ24ubWF0KQ0KIyBoZWFkKG1jJHNjYWxlLmRzZ24ubWF0KQ0KIyBoZWFkKG1jJHNoYXBlLmRzZ24ubWF0KQ0KDQojIHRpZHliYXllczo6YWRkX3Jlc2lkdWFsX2RyYXdzKG1jJGNoYWluLmxvY1ssNjoxMF0pDQoNCiMgbW9kMV9zaW0gPC0gY29kYTo6Y29kYS5zYW1wbGVzKG1vZGVsID0gbWMsIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZXMgPSBjaGFpbi5sb2MsDQogICAgICAgICAgICAgICAgICAgICAgICAgIyBuLml0ZXIgPSA1MDAwKQ0KYGBgDQoNCmRzZ24ubWF0IFRoZSBkZXNpZ24gbWF0cml4Lg0KDQpzaWxsID0gdW1icmFsDQoNCnJhbmdlcyA9IHJhbmdvDQoNCnNtb290aHMgPSBmb3JtYQ0KDQoNCiMjIyBkaWFnbm9zdGljb3MNCg0KVW4gdmVjdG9yIGRlIGxvbmdpdHVkIDMgcXVlIGRldnVlbHZlIGVsIERJQywgZWwgbsO6bWVybyBlZmVjdGl2byBkZSBwYXLDoW1ldHJvcyBlTm9QIHkgdW5hIGVzdGltYWNpw7NuIGRlIGxhIGRlc3ZpYWNpw7NuIGVzcGVyYWRhIERiYXIuDQoNCmBgYHtyfQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkoY29kYSkNCmxpYnJhcnkoYnJvb20ubWl4ZWQpDQpsaWJyYXJ5KGJybXMpDQpsaWJyYXJ5KGJheWVzcGxvdCkNCmBgYA0KDQpwYXJhbWV0cm8gZGUgbG9jYWxpemFjacOzbg0KDQpgYGB7cn0NCm1jMSRjaGFpbi5sb2MgPC0gYXMuZGF0YS5mcmFtZShtYzEkY2hhaW4ubG9jKSAlPiUgDQogIG11dGF0ZShjaGFpbiA9IDEpDQptYzIkY2hhaW4ubG9jIDwtIGFzLmRhdGEuZnJhbWUobWMyJGNoYWluLmxvYykgJT4lIA0KICBtdXRhdGUoY2hhaW4gPSAyKQ0KbWMzJGNoYWluLmxvYyA8LSBhcy5kYXRhLmZyYW1lKG1jMyRjaGFpbi5sb2MpICU+JSANCiAgbXV0YXRlKGNoYWluID0gMykNCg0KbWMubG9jIDwtICBtYzEkY2hhaW4ubG9jICU+JSANCiAgdW5pb25fYWxsKG1jMiRjaGFpbi5sb2MpICU+JSB1bmlvbl9hbGwobWMzJGNoYWluLmxvYykNCg0KcG9zdCA8LSBwb3N0ZXJpb3Jfc2FtcGxlcyhtYy5sb2MsIGFkZF9jaGFpbiA9IFQpDQptY21jX2RlbnNfb3ZlcmxheShwb3N0KQ0KDQoNCnBvc3QgJT4lIA0KICBzZWxlY3QobG0xLCBzaWxsLCByYW5nZSwgbG9jMSwgbG9jMiwgbG9jMywgbG9jNCkgJT4lIA0KICBtY21jX2FjZigpDQoNCnBvc3QgJT4lIA0KICBzZWxlY3QobG0xLCBzaWxsLCByYW5nZSwgbG9jMSwgbG9jMiwgbG9jMywgbG9jNCkgJT4lIA0KICBtY21jX3RyYWNlKCkNCg0KcG9zdCAlPiUgDQogIHNlbGVjdChsbTEsIHNpbGwsIHJhbmdlLCBsb2MxLCBsb2MyLCBsb2MzLCBsb2M0KSAlPiUgDQogIG1jbWNfZGVucygpDQoNCg0KcG9zdCAlPiUgc2VsZWN0KGxtMSkgJT4lIG1jbWNfdHJhY2UoKQ0KDQoNCmxpYnJhcnkoY29kYSkNCg0KY29kYTo6cmFmdGVyeS5kaWFnKHBvc3Rlcmlvcl9zYW1wbGVzKHBvc3QpKQ0KDQojIGNvZGE6OmdlbG1hbi5kaWFnKG1jbWMubGlzdChhcy5tY21jKG1jMSRjaGFpbi5sb2NbLGMoLTQsLTkpXSksIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzIkY2hhaW4ubG9jWyxjKC00LC05KV0pLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMzJGNoYWluLmxvY1ssYygtNCwtOSldKSkpDQojIA0KIyBjb2RhOjpnZWxtYW4uZGlhZyhtY21jLmxpc3QoYXMubWNtYyhtYzEkY2hhaW4ubG9jWywxXSksIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzIkY2hhaW4ubG9jWywxXSksIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzMkY2hhaW4ubG9jWywxXSkpKQ0KDQpCTXUxLm1jbWM8LW1jbWMubGlzdChhcy5tY21jKG1jMSRjaGFpbi5sb2NbLGMoLTQsLTkpXSksIA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzIkY2hhaW4ubG9jWyxjKC00LC05KV0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzMkY2hhaW4ubG9jWyxjKC00LC05KV0pKQ0KDQpzdW1tYXJ5KEJNdTEubWNtYykNCnh5cGxvdChCTXUxLm1jbWMpDQpkZW5zaXR5cGxvdChCTXUxLm1jbWMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjRGVuc2lkYWRlcw0KcGxvdChCTXUxLm1jbWMpDQojIGxheW91dChtYXRyaXgoMToxMiwgMyw0KSk7ICANCg0KdHJhY2VwbG90KEJNdTEubWNtYykNCg0KI0dyYWZpY2EgZGUgYXV0b2NvcnJlbGFjaW9uDQphdXRvY29yci5wbG90KEJNdTEubWNtYywgYXV0by5sYXlvdXQgPSBUUlVFLCBhc2sgPUYpDQpjb2RhOjphY2ZwbG90KEJNdTEubWNtYykNCg0KIyBnZWxtYW4uZGlhZyhCTXUxLm1jbWMpDQojIA0KIyBnZWxtYW4ucGxvdChCTXUxLm1jbWMpDQoNCmdld2VrZS5kaWFnKEJNdTEubWNtYykNCiNnZXdla2UucGxvdChCTXUxLm1jbWMpDQpyYWZ0ZXJ5LmRpYWcoQk11MS5tY21jKQ0KIyBoZWlkZWwuZGlhZyhCTXUxLm1jbWMpDQoNCg0KYGBgDQoNCg0KDQpwYXJhbWV0cm8gZGUgZXNjYWxhDQoNCmBgYHtyfQ0KbWMxJGNoYWluLnNjYWxlIDwtIGFzLmRhdGEuZnJhbWUobWMxJGNoYWluLnNjYWxlKSAlPiUgDQogIG11dGF0ZShjaGFpbiA9IDEpDQptYzIkY2hhaW4uc2NhbGUgPC0gYXMuZGF0YS5mcmFtZShtYzIkY2hhaW4uc2NhbGUpICU+JSANCiAgbXV0YXRlKGNoYWluID0gMikNCm1jMyRjaGFpbi5zY2FsZSA8LSBhcy5kYXRhLmZyYW1lKG1jMyRjaGFpbi5zY2FsZSkgJT4lIA0KICBtdXRhdGUoY2hhaW4gPSAzKQ0KDQptYy5sb2MgPC0gIG1jMSRjaGFpbi5zY2FsZSAlPiUgDQogIHVuaW9uX2FsbChtYzIkY2hhaW4uc2NhbGUpICU+JSB1bmlvbl9hbGwobWMzJGNoYWluLnNjYWxlKQ0KDQpwb3N0IDwtIHBvc3Rlcmlvcl9zYW1wbGVzKG1jLmxvYywgYWRkX2NoYWluID0gVCkNCm1jbWNfZGVuc19vdmVybGF5KHBvc3QpDQoNCg0KcG9zdCAlPiUgDQogIHNlbGVjdChsbTEsIHNpbGwsIHJhbmdlLCBzY2FsZTEsIHNjYWxlMiwgc2NhbGUzLCBzY2FsZTQpICU+JSANCiAgbWNtY19hY2YoKQ0KDQpwb3N0ICU+JSANCiAgc2VsZWN0KGxtMSwgc2lsbCwgcmFuZ2UsIHNjYWxlMSwgc2NhbGUyLCBzY2FsZTMsIHNjYWxlNCkgJT4lIA0KICBtY21jX3RyYWNlKCkNCg0KcG9zdCAlPiUgDQogIHNlbGVjdChsbTEsIHNpbGwsIHJhbmdlLCBzY2FsZTEsIHNjYWxlMiwgc2NhbGUzLCBzY2FsZTQpICU+JSANCiAgbWNtY19kZW5zKCkNCg0KDQpwb3N0ICU+JSBzZWxlY3QobG0xKSAlPiUgbWNtY190cmFjZSgpDQoNCg0KbGlicmFyeShjb2RhKQ0KDQpjb2RhOjpyYWZ0ZXJ5LmRpYWcocG9zdGVyaW9yX3NhbXBsZXMocG9zdCkpDQoNCiMgY29kYTo6Z2VsbWFuLmRpYWcobWNtYy5saXN0KGFzLm1jbWMobWMxJGNoYWluLnNjYWxlWyxjKC00LC05KV0pLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMyJGNoYWluLnNjYWxlWyxjKC00LC05KV0pLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMzJGNoYWluLnNjYWxlWyxjKC00LC05KV0pKSkNCiMgDQojIGNvZGE6OmdlbG1hbi5kaWFnKG1jbWMubGlzdChhcy5tY21jKG1jMSRjaGFpbi5zY2FsZVssMV0pLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMyJGNoYWluLnNjYWxlWywxXSksIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzMkY2hhaW4uc2NhbGVbLDFdKSkpDQoNCkJNdTEubWNtYzwtbWNtYy5saXN0KGFzLm1jbWMobWMxJGNoYWluLnNjYWxlWyxjKC00LC05KV0pLCANCiAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMyJGNoYWluLnNjYWxlWyxjKC00LC05KV0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYzMkY2hhaW4uc2NhbGVbLGMoLTQsLTkpXSkpDQoNCnN1bW1hcnkoQk11MS5tY21jKQ0KeHlwbG90KEJNdTEubWNtYykNCmRlbnNpdHlwbG90KEJNdTEubWNtYykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNEZW5zaWRhZGVzDQpwbG90KEJNdTEubWNtYykNCiMgbGF5b3V0KG1hdHJpeCgxOjEyLCAzLDQpKTsgIA0KDQp0cmFjZXBsb3QoQk11MS5tY21jKQ0KDQojR3JhZmljYSBkZSBhdXRvY29ycmVsYWNpb24NCmF1dG9jb3JyLnBsb3QoQk11MS5tY21jLCBhdXRvLmxheW91dCA9IFRSVUUsIGFzayA9RikNCmNvZGE6OmFjZnBsb3QoQk11MS5tY21jKQ0KDQojIGdlbG1hbi5kaWFnKEJNdTEubWNtYykNCiMgDQojIGdlbG1hbi5wbG90KEJNdTEubWNtYykNCg0KZ2V3ZWtlLmRpYWcoQk11MS5tY21jKQ0KI2dld2VrZS5wbG90KEJNdTEubWNtYykNCnJhZnRlcnkuZGlhZyhCTXUxLm1jbWMpDQojIGhlaWRlbC5kaWFnKEJNdTEubWNtYykNCg0KDQpgYGANCg0KDQoNCg0KDQoNCnBhcmFtZXRybyBkZSBmb3JtYQ0KDQpgYGB7cn0NCm1jMSRjaGFpbi5zaGFwZSA8LSBhcy5kYXRhLmZyYW1lKG1jMSRjaGFpbi5zaGFwZSkgJT4lIA0KICBtdXRhdGUoY2hhaW4gPSAxKQ0KbWMyJGNoYWluLnNoYXBlIDwtIGFzLmRhdGEuZnJhbWUobWMyJGNoYWluLnNoYXBlKSAlPiUgDQogIG11dGF0ZShjaGFpbiA9IDIpDQptYzMkY2hhaW4uc2hhcGUgPC0gYXMuZGF0YS5mcmFtZShtYzMkY2hhaW4uc2hhcGUpICU+JSANCiAgbXV0YXRlKGNoYWluID0gMykNCg0KbWMubG9jIDwtICBtYzEkY2hhaW4uc2hhcGUgJT4lIA0KICB1bmlvbl9hbGwobWMyJGNoYWluLnNoYXBlKSAlPiUgdW5pb25fYWxsKG1jMyRjaGFpbi5zaGFwZSkNCg0KcG9zdCA8LSBwb3N0ZXJpb3Jfc2FtcGxlcyhtYy5sb2MsIGFkZF9jaGFpbiA9IFQpDQptY21jX2RlbnNfb3ZlcmxheShwb3N0KQ0KDQoNCnBvc3QgJT4lIA0KICBzZWxlY3QobG0xLCBzaWxsLCByYW5nZSwgc2hhcGUxLCBzaGFwZTIsIHNoYXBlMywgc2hhcGU0KSAlPiUgDQogIG1jbWNfYWNmKCkNCg0KcG9zdCAlPiUgDQogIHNlbGVjdChsbTEsIHNpbGwsIHJhbmdlLCBzaGFwZTEsIHNoYXBlMiwgc2hhcGUzLCBzaGFwZTQpICU+JSANCiAgbWNtY190cmFjZSgpDQoNCnBvc3QgJT4lIA0KICBzZWxlY3QobG0xLCBzaWxsLCByYW5nZSwgc2hhcGUxLCBzaGFwZTIsIHNoYXBlMywgc2hhcGU0KSAlPiUgDQogIG1jbWNfZGVucygpDQoNCg0KcG9zdCAlPiUgc2VsZWN0KGxtMSkgJT4lIG1jbWNfdHJhY2UoKQ0KDQoNCmxpYnJhcnkoY29kYSkNCg0KY29kYTo6cmFmdGVyeS5kaWFnKHBvc3Rlcmlvcl9zYW1wbGVzKHBvc3QpKQ0KDQojIGNvZGE6OmdlbG1hbi5kaWFnKG1jbWMubGlzdChhcy5tY21jKG1jMSRjaGFpbi5zaGFwZVssYygtNCwtOSldKSwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5tY21jKG1jMiRjaGFpbi5zaGFwZVssYygtNCwtOSldKSwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5tY21jKG1jMyRjaGFpbi5zaGFwZVssYygtNCwtOSldKSkpDQojIA0KIyBjb2RhOjpnZWxtYW4uZGlhZyhtY21jLmxpc3QoYXMubWNtYyhtYzEkY2hhaW4uc2hhcGVbLDFdKSwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5tY21jKG1jMiRjaGFpbi5zaGFwZVssMV0pLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMzJGNoYWluLnNoYXBlWywxXSkpKQ0KDQpCTXUxLm1jbWM8LW1jbWMubGlzdChhcy5tY21jKG1jMSRjaGFpbi5zaGFwZVssYygtNCwtOSldKSwgDQogICAgICAgICAgICAgICAgICAgICBhcy5tY21jKG1jMiRjaGFpbi5zaGFwZVssYygtNCwtOSldKSwNCiAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMzJGNoYWluLnNoYXBlWyxjKC00LC05KV0pKQ0KDQpzdW1tYXJ5KEJNdTEubWNtYykNCnh5cGxvdChCTXUxLm1jbWMpDQpkZW5zaXR5cGxvdChCTXUxLm1jbWMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjRGVuc2lkYWRlcw0KcGxvdChCTXUxLm1jbWMpDQojIGxheW91dChtYXRyaXgoMToxMiwgMyw0KSk7ICANCg0KdHJhY2VwbG90KEJNdTEubWNtYykNCg0KI0dyYWZpY2EgZGUgYXV0b2NvcnJlbGFjaW9uDQphdXRvY29yci5wbG90KEJNdTEubWNtYywgYXV0by5sYXlvdXQgPSBUUlVFLCBhc2sgPUYpDQpjb2RhOjphY2ZwbG90KEJNdTEubWNtYykNCg0KIyBnZWxtYW4uZGlhZyhCTXUxLm1jbWMpDQojIA0KIyBnZWxtYW4ucGxvdChCTXUxLm1jbWMpDQoNCmdld2VrZS5kaWFnKEJNdTEubWNtYykNCiNnZXdla2UucGxvdChCTXUxLm1jbWMpDQpyYWZ0ZXJ5LmRpYWcoQk11MS5tY21jKQ0KIyBoZWlkZWwuZGlhZyhCTXUxLm1jbWMpDQoNCg0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyLCBjYWNoZT1UUlVFLCBldmFsPUZBTFNFfQ0KRElDKG1jKQ0KDQp4LmdyaWQgPC0gc2VxKC05NSwgLTkwLCBsZW5ndGggPSAyMCkNCnkuZ3JpZCA8LSBzZXEoMTQsIDE5LCBsZW5ndGggPSAyMCkNCiMgbWFwLmxhdGVudChtYywgeC5ncmlkLCB5LmdyaWQsIHBhcmFtID0gImxvYyIpDQojIG1hcC5sYXRlbnQobWMsIHguZ3JpZCwgeS5ncmlkLCBwYXJhbSA9ICJsb2MiLCBwbG90LmNvbnRvdXIgPSBGKQ0KIyBtYXAubGF0ZW50KG1jLCB4LmdyaWQsIHkuZ3JpZCwgcGFyYW0gPSAibG9jIiwgcGxvdC5jb250b3VyID0gVCwgc2hvdy5kYXRhID0gRikNCiMgbWFwLmxhdGVudChtYywgeC5ncmlkLCB5LmdyaWQsIHBhcmFtID0gImxvYyIsIHBsb3QuY29udG91ciA9IFQsIHNob3cuZGF0YSA9IFQpDQoNCiMgaGVhZChtYyRjaGFpbi5sb2NbLDZdKQ0KIyBoZWFkKG1jJGNoYWluLnNjYWxlKQ0KIyBoZWFkKG1jJGNoYWluLnNoYXBlKQ0KIyBoZWFkKG1jJGxvYy5kc2duLm1hdCkNCiMgaGVhZChtYyRzY2FsZS5kc2duLm1hdCkNCiMgaGVhZChtYyREYmFyKQ0KIyBzdW1tYXJ5KG1jKQ0KbGlicmFyeShsYXR0aWNlKQ0KbGlicmFyeShjb2RhKQ0KIyBhdXRvY29yci5wbG90KGFzLm1jbWMobWMkY2hhaW4ubG9jWywxXSkpDQojIGNvZGE6OmdlbG1hbi5kaWFnKGFzLm1jbWMobWMkY2hhaW4ubG9jWywxXSkpDQpCTXUxLm1jbWM8LW1jbWMubGlzdChhcy5tY21jKG1jJGNoYWluLnNoYXBlWyw1XSksIA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zaGFwZVssNl0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zaGFwZVssN10pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zaGFwZVssOF0pKQ0KDQpzdW1tYXJ5KEJNdTEubWNtYykNCnh5cGxvdChCTXUxLm1jbWMpDQpkZW5zaXR5cGxvdChCTXUxLm1jbWMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjRGVuc2lkYWRlcw0KcGxvdChCTXUxLm1jbWMpDQojIGxheW91dChtYXRyaXgoMToxMiwgMyw0KSk7ICANCg0KdHJhY2VwbG90KEJNdTEubWNtYykNCg0KI0dyYWZpY2EgZGUgYXV0b2NvcnJlbGFjaW9uDQphdXRvY29yci5wbG90KEJNdTEubWNtYywgYXV0by5sYXlvdXQgPSBUUlVFLCBhc2sgPUYpDQpjb2RhOjphY2ZwbG90KEJNdTEubWNtYykNCg0KZ2VsbWFuLmRpYWcoQk11MS5tY21jKQ0KDQpnZWxtYW4ucGxvdChCTXUxLm1jbWMpDQoNCmdld2VrZS5kaWFnKEJNdTEubWNtYykNCiNnZXdla2UucGxvdChCTXUxLm1jbWMpDQpyYWZ0ZXJ5LmRpYWcoQk11MS5tY21jKQ0KIyBoZWlkZWwuZGlhZyhCTXUxLm1jbWMpDQoNCg0KbGlicmFyeShsYXR0aWNlKQ0KbGlicmFyeShjb2RhKQ0KQk11MS5tY21jPC1tY21jLmxpc3QoYXMubWNtYyhtYyRjaGFpbi5sb2NbLDVdKSwNCiAgICAgICAgICAgICAgICAgICAgIGFzLm1jbWMobWMkY2hhaW4ubG9jWyw2XSksDQogICAgICAgICAgICAgICAgICAgICBhcy5tY21jKG1jJGNoYWluLmxvY1ssN10pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5sb2NbLDhdKSkNCg0Kc3VtbWFyeShCTXUxLm1jbWMpDQp4eXBsb3QoQk11MS5tY21jKQ0KZGVuc2l0eXBsb3QoQk11MS5tY21jKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI0RlbnNpZGFkZXMNCnBsb3QoQk11MS5tY21jKQ0KIyBsYXlvdXQobWF0cml4KDE6MTIsIDMsNCkpOyAgDQoNCnRyYWNlcGxvdChCTXUxLm1jbWMpDQoNCiNHcmFmaWNhIGRlIGF1dG9jb3JyZWxhY2lvbg0KYXV0b2NvcnIucGxvdChCTXUxLm1jbWMsIGF1dG8ubGF5b3V0ID0gVFJVRSwgYXNrID1GKQ0KY29kYTo6YWNmcGxvdChCTXUxLm1jbWMpDQoNCmdlbG1hbi5kaWFnKEJNdTEubWNtYykNCg0KZ2VsbWFuLnBsb3QoQk11MS5tY21jKQ0KDQpnZXdla2UuZGlhZyhCTXUxLm1jbWMpDQojZ2V3ZWtlLnBsb3QoQk11MS5tY21jKQ0KIyByYWZ0ZXJ5LmRpYWcoQk11MS5tY21jKQ0KIyBoZWlkZWwuZGlhZyhCTXUxLm1jbWMpDQoNCg0KQk11MS5tY21jPC1tY21jLmxpc3QoYXMubWNtYyhtYyRjaGFpbi5zY2FsZVssNl0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zY2FsZVssN10pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zY2FsZVssOF0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zY2FsZVssOV0pLA0KICAgICAgICAgICAgICAgICAgICAgYXMubWNtYyhtYyRjaGFpbi5zY2FsZVssMTBdKSkNCg0Kc3VtbWFyeShCTXUxLm1jbWMpDQp4eXBsb3QoQk11MS5tY21jKQ0KZGVuc2l0eXBsb3QoQk11MS5tY21jKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI0RlbnNpZGFkZXMNCnBsb3QoQk11MS5tY21jKQ0KIyBsYXlvdXQobWF0cml4KDE6MTIsIDMsNCkpOyAgDQoNCnRyYWNlcGxvdChCTXUxLm1jbWMpDQoNCiNHcmFmaWNhIGRlIGF1dG9jb3JyZWxhY2lvbg0KYXV0b2NvcnIucGxvdChCTXUxLm1jbWMsIGF1dG8ubGF5b3V0ID0gVFJVRSwgYXNrID1GKQ0KY29kYTo6YWNmcGxvdChCTXUxLm1jbWMpDQoNCmdlbG1hbi5kaWFnKEJNdTEubWNtYykNCg0KZ2VsbWFuLnBsb3QoQk11MS5tY21jKQ0KDQpnZXdla2UuZGlhZyhCTXUxLm1jbWMpDQojZ2V3ZWtlLnBsb3QoQk11MS5tY21jKQ0KcmFmdGVyeS5kaWFnKEJNdTEubWNtYykNCiMgaGVpZGVsLmRpYWcoQk11MS5tY21jKQ0KDQpgYGANCg0KDQo=